source("scr/libraries.R")
source("scr/ggplot.R")
source("scr/VCFfilterstats.R")
source("scr/HaplotypR.R")
source("scr/xtrafunctions.R")
source("scr/genind.R")

Read mapping

Map reads

Any renaming of files needs to happen before fastq-files are mapped. The population designation (before underscore) is used by FreeBayes to call SNPs so it is important that population designation make biological sense.

Values chosen for reduced representation reference:

  • c = 0.8
  • K1 = 5
  • K2 = 2

Transfer copy of reference.fasta and associated files Reference constructed using c = 0.8, K1 = 5, and K2 = 2. into each directory containing demultiplexed and quality trimmed data/SEQ

Run dDocent from within each Library directory to map reads to reference.fasta.

Write configuration file to run dDocent in each reference directory.

Execute dDocent from within each reference folder to initiate a run to map individuals to reduced representation reference and call SNPs.

QA/QC read mapping

Query mapping statistics

During the mapping stage, dDocent calls BWA to map reads from the individuals in the folder to the generated reduced representation reference and create a -RG.bam-file for each individual. The second column of a BAM (or SAM) file contains FLAGs with binary encoded information on mapping quality, pairedness etc. that can be used to compare the mapping efficiency to the reduced representation reference.

The number of reads mapped can be counted using samtools idxstats <aln-RG.bam> which retrieves stats from the bam-file. The output is TAB-delimited file with each line consisting of the reference sequence name, sequence length, # mapped reads and # unmapped (empty) reads. In addition, samtools can also be be used to query samtools flagstat file.bam which returns an output containing the number of reads for which each flag is true.

dDocent creates a file called bamlist.list containing all the bam files that were generated during read mapping in dDocent using BWA. Write script to gather flagstats from all bam-files.

Run flagstats.

Write script to gather idxstats from all bam-files.

Run indxstats.

Format stats files into tidy data sets

Appending the file results in the information per individual being printed in a new set of row being appended to the file, i.e. there will be as many rows for a given locus as individuals were mapped. The file can be re-formatted and summary statistics calculated using dplyr and tidyr.

Format idxstats:


# create vectors of files to be imported, reference codes, K1 and K2, dataframe names
filenames <- list.files(path = "data/SEQ", pattern = "*.idxstats")
names <- substr(filenames, 1, 8)
lib <- substr(filenames, 1, 4)

# import data
for (i in names){
  filepath <- file.path("data/SEQ", paste(i, 'stats', sep =""))
  assign(i, read.table(filepath, sep = "", header = FALSE,
                     col.names = c("Locus", "Length", "Reads_Mapped", 'blank')) %>%
           select(1:3))
  }

# # make sure to delete old list if rerunning the code
rm(dflist_idx)
rm(MapStats.idx)

# Create list of one dataframe per idxstats file and group by locus
dflist_idx <- lapply(ls(pattern = "*.idx"), get)

for (df in 1:length(dflist_idx)){
  x <- dflist_idx[[df]]
  x[['Locus']] <- as.character(x[['Locus']])
  x = x %>% group_by(Locus)
  dflist_idx[[df]] <- x
}

# Create new dataframes with summary stats per library and bind into final output/dataframe
MapStats.idx <- data.frame()

for (df in 1:length(dflist_idx)){
    
  x = summarize(dflist_idx[[df]],
                Length = mean(Length),
                Mean_Mapped = mean(Reads_Mapped),
                Sum_Mapped = sum(Reads_Mapped),
                Min_Mapped = min(Reads_Mapped),
                Max_Mapped = max(Reads_Mapped),
                SD_Mapped = sd(Reads_Mapped))
  x[x == 0] <- NA

  temp <- summarize(x, Mean_Mapped_Non0 = mean(Mean_Mapped, na.rm = TRUE)) %>%
    mutate(Lib = lib[df],
           Not_Mapped = nrow(filter(x, is.na(Sum_Mapped))),
           N_Loci_Ref = nrow(x)) %>%
    select(Lib, N_Loci_Ref, Not_Mapped, Mean_Mapped_Non0)

  MapStats.idx <- bind_rows(MapStats.idx, temp)
}

MapStats.idx <- MapStats.idx %>%
  mutate(PROP_EMPTY = round((Not_Mapped/N_Loci_Ref)*100, digits = 2),
         CONTIGS_MAPPED = N_Loci_Ref - Not_Mapped)

write.table(MapStats.idx, "results/MapStats.idx", quote = FALSE)

# remove large (duplicate) files
rm(BMA1.idx)
rm(BMA2.idx)
rm(BMA3.idx)

MapStats.idx

Format flagstats:


# Files to be imported
filenames <- list.files(path='data/SEQ', pattern = '*.flagstats')

# create vectors of files to be imported
names <- substr(filenames, 1, 9)
lib <- substr(filenames, 1, 4)

# import data
for (i in names){
  filepath <- file.path('data/SEQ', paste(i, 'stats', sep =""))
  assign(i, read.csv(filepath, sep = "+", header = FALSE,
                     col.names = c("N_Reads", "CAT"),
                     stringsAsFactors = FALSE) %>%
           select(1:2))
}

# Create list of one dataframe per flagstats file and create tidy data set
# should be 3 elements/libraries
rm(dflist_flag)

dflist_flag <- lapply(ls(pattern = "*flag"), get)

# Change N_Reads to numeric
for (df in 1:length(dflist_flag)){
  x <- dflist_flag[[df]]
  x[['N_Reads']] <- as.numeric(x[['N_Reads']])
  dflist_flag[[df]] <- x
}

for (df in 1:length(dflist_flag)){
  x <- dflist_flag[[df]]
  
  n <- nrow(x)/14

  x <- x %>%
    filter(grepl("0 mapped|properly paired|mapQ>=5", CAT)) %>%
    mutate(MAPSTAT = ifelse(grepl("mapQ>=5", CAT), "Mismatch",
                   ifelse(grepl("properly", CAT), "Prop_Paired", "Mapped"))) %>%
    mutate(Ind = c(rep(1:n, each = 3))) %>% 
    # not sure if extra individual in there somehow
    select(4, 3, 1) %>%
    spread(MAPSTAT, N_Reads)

  dflist_flag[[df]] <- x
}

# Create new dataframes with summary stats and add to main final data frame
MapStats.flag <- data.frame()

for (df in 1:length(dflist_flag)){
  x = summarize(dflist_flag[[df]], Sum_Mapped = sum(Mapped),
                             Reads_Mapped = mean(Mapped),
                             Sum_Paired = sum(Prop_Paired),
                             Mean_Paired = mean(Prop_Paired),
                             Sum_Mismatch = sum(Mismatch),
                             Mean_Mismatch = mean(Mismatch)) %>%
  mutate(Lib = lib[df]) %>%
  select(7, 1:6)
  MapStats.flag <- bind_rows(MapStats.flag, x)
}

# write to file
write.table(MapStats.flag, "results/MapStats.flag", quote = FALSE)

MapStats.flag

# combine files
mapstats <- left_join(MapStats.idx, MapStats.flag) %>%
  mutate(PROP_MISMATCH = Sum_Mismatch/Sum_Mapped)

# write summary stats file
write.table(mapstats, file = "results/BWA_mapping.stats", quote = FALSE, sep = " ")

SNP calling

Transfer copy of reference.fasta and associated files into SNP calling directory.

Create symlinks from all fq, bam and bam.bai-files for each separately mapped library in SNP_Calling folder.

Execute dDocent from within SNP_Calling-folder to call variants across all individuals (all libraries).

File TotalrawSNPs.vcf contains all raw SNP/INDEL calls. Do not need to keep links of fq.gz-, bam-, .bam.bai-files after SNPs have been called. Copy TotalRaSNPs.vcf to VCF for SNP filtering.

SNP filtering

dDocent uses FreeBayes to call SNPs and write a VCF-file TotalrawSNPs.vcf. This data set was filtered to remove low quality and artefactual SNP sites, paralogs and low quality individuals based on levels of missing data, minimum/maximum read depth, genotype call rate, and minor allele frequencies. Contigs may contain more than one SNP; the script rad_haplotyper.pl was used to create haplotypes for each locus.

Raw data

Compare Individual & SNP stats

Use VCFtools to create stats files for depth, missing data, heterozygosity and site quality for the raw data.

Compare raw stats.


# load stats files ----
ind_stats_raw <- read.ind.stats(dir = "data/VCF", vcf = "BMA_raw") %>%
  separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE)

loc_stats_raw <- read.loc.stats(dir = "data/VCF/", vcf = "BMA_raw")

# plot missing data per indv ----
p1 <- ggplot(ind_stats_raw, aes(x = MISS_BMA_raw)) +
  geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.5),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "missing data per indv") +
  theme_standard

# plot read depth per indv ----
p2 <- ggplot(ind_stats_raw, aes(x = MEAN_DEPTH_BMA_raw)) +
  geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per indv") +
  theme_standard

# plot depth vs missing ----
p3 <- ggplot(ind_stats_raw, aes(x = MEAN_DEPTH_BMA_raw, y = MISS_BMA_raw)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.5),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per indv", y = "% missing data") +
  theme_standard

# plot Fis per indv ----
p4 <- ggplot(ind_stats_raw, aes(x = Fis_BMA_raw)) +
  geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(Fis_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv") +
  theme_standard

# plot Fis vs missing data per indv ----
p5 <- ggplot(ind_stats_raw, aes(x = Fis_BMA_raw, y = MISS_BMA_raw)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(Fis_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.5),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv", y = "% missing data") +
  theme_standard

# plot Fis vs mean depth per indv ----
p6 <- ggplot(ind_stats_raw, aes(x = Fis_BMA_raw, y = MEAN_DEPTH_BMA_raw)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(Fis_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv", y = "mean depth per indv") +
  theme_standard


# plot distribution missing data per locus ----
p7 <- ggplot(loc_stats_raw, aes(x = MISS_BMA_raw)) +
  geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.1),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "% missing data per locus") +
  theme_standard

# plot distribution mean read depth ----
p8 <- ggplot(loc_stats_raw, aes(x = MEAN_DEPTH_BMA_raw)) +
  geom_histogram(binwidth = 20, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per locus") +
  theme_standard

# plot read depth vs missing data ----
p9 <- ggplot(loc_stats_raw, aes(x = MEAN_DEPTH_BMA_raw, y = MISS_BMA_raw)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA_raw, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.1),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per locus", y = "% missing data") +
  theme_standard

# plot depth vs SNP quality ----
site_qual <- read.table("data/VCF/BMA_raw.lqual", 
                        header = TRUE, stringsAsFactors = FALSE) %>%
  mutate(PROB = 10^(-QUAL/10))

temp <- data.frame(loc_stats_raw$MEAN_DEPTH_BMA_raw, site_qual$QUAL) %>%
  rename(depth = loc_stats_raw.MEAN_DEPTH_BMA_raw, qual = site_qual.QUAL)

p10 <- ggplot(temp, aes(x = depth, y = qual)) +
  geom_point(size = 1) +
  geom_vline(aes(xintercept = mean(depth, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(qual, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per locus", y = "SNP quality") +
  theme_standard

# plot number of SNPs per contig vs. mean depth ----
temp <- loc_stats_raw %>%
  count(CHR)

p11 <- left_join(temp, loc_stats_raw) %>%
  ggplot() +
  geom_point(aes(x = n, y = MEAN_DEPTH_BMA_raw)) +
  labs(x = "number of SNPs per contig", y = "mean depth") +
  theme_standard

# plot no of SNPs per locus ----
p12 <- loc_stats_raw %>%
  count(CHR) %>%
  ggplot(aes(x = n)) +
  geom_histogram(binwidth = 1, color = "black", fill = "darkorange") + 
  labs(x = "number of SNPs per locus") +
  theme_standard

mraw <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, cols=2)

Choose threshold values for quality score, coverage, missing data, minor alleles and mapping/variant calling artifacts

Filter 0: Remove LQ individuals

Remove (known) low quality individuals from data set:

Identify low quality individuals to remove from the data set; defined as individuals with a mean coverage of five or less reads across all loci, with more than 31% missing data, or Fis > (thresholds based on exploratory filtering).

[1] 18

Remove low quality individuals and decompose indels.

Compare stats:

Data set contains 406 individuals and 1311068 loci after removing low quality individuals and decomposing indels set into SNPs.

Import singletons and genotype depth file to create list of loci to exclude based on depth.

Data set contains nrow(singletons) singletons.

Of those nrow(doubletons) are called as a homozygote in one individual.

The data set contains nrow(contigs_total) contigs, nrow(contigs_singletons) (2round( (nrow(contigs_singletons)/nrow(contigs_total)*100), digits = 2)%) contain singletons.

Target coverage is 20 reads per locus; flag singletons with depth < 10 reads and doubletons with depth < 20 reads.

Distriubtion of genotype depth per singleton/doubleton.

Quantiles distribution of read depth for SNP loci called in only one individual.

 5% 25% 50% 75% 95% 99% 
  1   3   5  10  32 139 

Distribution of doubletons (homzygous genotype for that individual) and singletons (heterozygote genotype).

Quantiles distribution number of singletons called in one individual.

     1%      5%     25%     50%     75%     99% 
  46.00   56.00   88.75  327.50  534.25 1815.90 

Compare the number of SNPs vs complex variants (INDELs).

Filter 1: Confidence in SNP call

The QUAL column of a VCF file is a phred based score indicating the probability that the variant shown in the ALT column is wrong. Given the Phred quality score (Q), and the probability that a base is incorrectly called (P), Q = -10(Log10P). A quality score of 20 indicates, a 1 in 100 chance that the SNP site has been called incorrectly (i.e. 99% probability that correct call).

Filter loci with quality score < 20 and singletons/doubletons with low read depth (<10/20 reads). Code genotypes with genotype call quality < 20 or genotype depth < 5 as missing.

Compare stats post-filtering.

Data set contains 406 individuals and 307278 SNP sites.

Removing low confidence SNP loci and genotype calls results in a reduction in the number of the (maximum) SNPs per locus.

Coding genotypes with low read depth (< 5) as missing, results in an overall increase in missing data per locus and a shift in more individuals with more missing data - this is because individuals (and loci) with coverage issues are now characterized by higher missing data.

Compare depth individuals after removing LQ SNP loci and genotypes.

Filter 2: Genotype call rate and allowed missing data per indv

Remove loci with genotype call rate < 50% and minimum mean depth < 15 reads across all individuals.


vcftools --vcf data/VCF/temp/BMA.F1.recode.vcf --out data/VCF/temp/BMA.F2a --max-missing 0.5 --min-meanDP 15 --recode --recode-INFO-all

# library BMA-1
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/BMA1 --keep data/VCF/BMA1.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/BMA1.recode.vcf --out data/VCF/BMA1 --missing-site

# library BMA-2
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/BMA2 --keep data/VCF/BMA2.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/BMA2.recode.vcf --out data/VCF/BMA2 --missing-site

# library BMA-3
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/BMA3 --keep data/VCF/BMA3.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/BMA3.recode.vcf --out data/VCF/BMA3 --missing-site

# Campeche
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/CAMP --keep data/VCF/CAMP.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/CAMP.recode.vcf --out data/VCF/CAMP --missing-site

# Chandeleur Sound
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/CS --keep data/VCF/CS.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/CS.recode.vcf --out data/VCF/CS --missing-site

# Corpus Christi Bay
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/CC --keep data/VCF/CC.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/CC.recode.vcf --out data/VCF/CC --missing-site

# Florida Atlantic
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/FLA --keep data/VCF/FLA.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/FLA.recode.vcf --out data/VCF/FLA --missing-site

# Florida Gulf South
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/FLGS --keep data/VCF/FLGS.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/FLGS.recode.vcf --out data/VCF/FLGS --missing-site

# Florida Gulf North
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/FLGN --keep data/VCF/FLGN.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/FLGN.recode.vcf --out data/VCF/FLGN --missing-site

# Louisiana
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/LA --keep data/VCF/LA.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/LA.recode.vcf --out data/VCF/LA --missing-site

# Mississippi Sound
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/MISS --keep data/VCF/MISS.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/MISS.recode.vcf --out data/VCF/MISS --missing-site

# Mobile Bay
vcftools --vcf data/VCF/temp/BMA.F2a.recode.vcf --out data/VCF/temp/MB --keep data/VCF/MB.ind  --recode --recode-INFO-all

vcftools --vcf data/VCF/temp/MB.recode.vcf --out data/VCF/MB --missing-site

Compare distribution of missing data per locus per library.

Flag loci that were not called in > 50% of individuals in a given library.

A total of

loci were called in less than 50% of individuals in one or more libraries. Loci being inconsistently called between libraries can result in library effects.

Compare distribution of missing data per locus per sample location.

Flag loci that were not called in > 75% of individuals at a given sample location.

Remove loci that were not consistently called across all libraries and sample locations.

Identify individuals with > 25% missing data

Remove flagged individuals.

Analyze stats post-filtering:

Filter 3: Filter loci and individuals based on depth, variance in depth and genotype call rate

Determine mean depth and variance per locus per library.

Compare distribution of depth coverage per locus per library. Identify loci that do not have consistent coverage between libraries (can lead to library effects), and/or across individuals.

Identify loci with large variance in mean depth across libraries and/or individuals by calculating the coefficient of variance (STD/MEAN).

Compare mean across all individual to mean weighted by library and coefficient of variance of read depth across individuals and between libraries:

If loci have consistent coverage across loci the mean read depth per locus across all individuals and weighted by library should fall on the red diagonal.

Flag loci that have high variation in mean coverage between individuals and between libraries.

Remove loci flagged for high variance in depth across all individuals and between libraries (removes library effects), filter loci with mean depth < 20 and genotype call rate < 75%

Compare mean depth and number of sites called per individual.

Use genotype depth file to identify individuals with high variance in read depth across loci.

Compare variability of depth within individuals.


p1 <- ggplot(idepth, aes(x = MAX, y = TOTAL)) +
  geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
  geom_point(shape = 1) +
  theme_standard

p2 <- ggplot(idepth, aes(x = TOTAL, y = VAR)) +
  geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
  geom_point(shape = 1) +
  theme_standard

p3 <- ggplot(idepth, aes(MAX, MEDIAN)) +
  geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
  geom_point(shape = 1) +
  theme_standard

p4 <- ggplot(idepth, aes(x = MEAN, y = MEDIAN)) +
  geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
  geom_point(shape = 1) +
  theme_standard

p5 <- ggplot(idepth, aes(x = COEFF_VAR, y = RATIO_MEAN_MEDIAN)) +
  geom_smooth(method = "auto",linetype = "dashed", size = 1, color = "darkred") +
  geom_point(shape = 1) +
  theme_standard

p6 <- ggplot(idepth, aes(MEAN)) +
  geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
  geom_vline(xintercept = 15, color = "darkred", linetype = "dashed") +
  theme_standard

p7 <- ggplot(idepth, aes(MEDIAN)) +
  geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
  geom_vline(xintercept = 10, color = "darkred", linetype = "dashed") +
  theme_standard

p8 <- ggplot(idepth, aes(RATIO_MEAN_MEDIAN)) +
  geom_histogram(binwidth = 0.1, color = "black", fill = "darkorange") +
  theme_standard

p9 <- ggplot(idepth, aes(COEFF_VAR)) +
  geom_histogram(binwidth = 0.025, color = "black", fill = "darkorange") +
  theme_standard

p10 <- ggplot(idepth, aes(x = COEFF_VAR, y = MISS_BMA.F2)) +
  geom_point(shape = 1) +
  geom_hline(yintercept = 0.25, linetype = "dashed", color = "darkred", size = 0.75) +
  theme_standard


m3b <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, cols=2)

Flag LQ individuals.

Remove flagged loci and individuals.

Compare stats post-filtering:


# load stats files ----
ind_stats_F3 <- read.ind.stats(dir = "data/VCF", vcf = "BMA.F3") %>%
  separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE)

loc_stats_F3 <- read.loc.stats(dir = "data/VCF/", vcf = "BMA.F3")

# plot missing data per indv ----
p1 <- ggplot(ind_stats_F3, aes(x = MISS_BMA.F3)) +
  geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA.F3, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.25),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "missing data per indv") +
  theme_standard

# plot read depth per indv ----
p2 <- ggplot(ind_stats_F3, aes(x = MEAN_DEPTH_BMA.F3)) +
  geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F3, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per indv") +
  theme_standard

# plot depth vs missing ----
p3 <- ggplot(ind_stats_F3, aes(x = MEAN_DEPTH_BMA.F3, y = MISS_BMA.F3)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F3, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
             color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.F3, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.25),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per indv", y = "% missing data") +
  theme_standard

# plot distribution missing data per locus ----
p4 <- ggplot(loc_stats_F3, aes(x = MISS_BMA.F3)) +
  geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA.F3, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.1),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "% missing data per locus") +
  theme_standard

# plot distribution mean read depth ----
p5 <- ggplot(loc_stats_F3, aes(x = MEAN_DEPTH_BMA.F3)) +
  geom_histogram(binwidth = 20, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F3, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per locus") +
  theme_standard

# plot read depth vs missing data ----
p6 <- ggplot(loc_stats_F3, aes(x = MEAN_DEPTH_BMA.F3, y = MISS_BMA.F3)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F3, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
             color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.F3, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.1),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per locus", y = "% missing data") +
  theme_standard

m3 <- multiplot(p1, p2, p3, p4, p5, p6, cols=2)

Filter 4: Allele balance

AB: Allele balance at heterozygous sites: a number between 0 and 1 representing the ratio of reads showing the reference allele to all reads, considering only reads from individuals called as heterozygous

Allele balance is the ratio of reads for reference allele to all reads, considering only reads from individuals called as heterozygous. Values range from 0 - 1; allele balance (for real loci) should be approx. 0.5. Filter SNPs for which the with allele balance < 0.25 and > 0.75.

Filter contigs with SNP calls with AB > 0.25, AB > 0.75; retain loci very close to 0 (retain loci that are fixed variants). Remove genotypes if the quality sum of the reference or alternate allele was 0.

Remaining SNPs: 52,610.

Filter 7: Strand balance

SRF: Number of reference observations on the forward strand SAF: Number of alternate observations on the forward strand SRR: Number of reference observations on the reverse strand SAR: Number of alternate observations on the reverse strand

Paired end reads should not overlap, and a SNP site should only be covered by either the forward or reverse read (strand).

Remove SNP sites that have > 100x more forward alternate reads than reverse alternate reads and > 100x more forward reverse reads than reverse alternate reads.

Number of SNPs remaining: 26,722.

Filter 8: Properly paired status

PAIRED: Proportion of observed alternate alleles which are supported by properly paired read fragments PAIREDR: Proportion of observed reference alleles which are supported by properly paired read fragments

Identify loci with only unpaired reads mapping to them - an artifact introduced due de novo reference assembly. Compare number of paired reads mapping the reference and the alternate alleles to identify discrepancy in the paired status for reads supporting reference and alternate alleles.

Number of SNPs in data set: 23,778.

Filter 9: Maximum depth & Quality

Identify distribution of depth (based on original data set) to identify loci with excess coverage.

Original number of individuals in data set is 424 (INFO flags in filtered data set are are based on original number of individuals in data set).

Create file with the original site depth and quality score for each site:

Calculate average depth and standard deviation:

Mean depth per locus (across all indivuals) is 3.867019810^{4} and the standard deviation is 4.218984410^{4}.

Filter SNP site with depth > mean depth + 1 standard deviation = 1.230498910^{5} and that have quality scores < 2x the depth at that site and output depth per site.

Compare the distribution of mean depth per site averaged across individuals to determine cut-off value of sites with excessively high depth indicative of paralogs/multicopy loci.

Choose cut-off for maximum mean read depth = 300.

Depth distribution per locus after filtering:

Analyze stats post-filtering:


# load stats files ----
ind_stats_F9 <- read.ind.stats(dir = "data/VCF", vcf = "BMA.F9") %>%
  separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE)

loc_stats_F9 <- read.loc.stats(dir = "data/VCF/", vcf = "BMA.F9")

# plot missing data per indv ----
p1 <- ggplot(ind_stats_F9, aes(x = MISS_BMA.F9)) +
  geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA.F9, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.25),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "missing data per indv") +
  theme_standard

# plot read depth per indv ----
p2 <- ggplot(ind_stats_F9, aes(x = MEAN_DEPTH_BMA.F9)) +
  geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F9, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per indv") +
  theme_standard

# plot depth vs missing ----
p3 <- ggplot(ind_stats_F9, aes(x = MEAN_DEPTH_BMA.F9, y = MISS_BMA.F9)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F9, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
             color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.F9, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.25),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per indv", y = "% missing data") +
  theme_standard

# plot distribution missing data per locus ----
p4 <- ggplot(loc_stats_F9, aes(x = MISS_BMA.F9)) +
  geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA.F9, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.1),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "% missing data per locus") +
  theme_standard

# plot distribution mean read depth ----
p5 <- ggplot(loc_stats_F9, aes(x = MEAN_DEPTH_BMA.F9)) +
  geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F9, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per locus") +
  theme_standard

# plot read depth vs missing data ----
p6 <- ggplot(loc_stats_F9, aes(x = MEAN_DEPTH_BMA.F9, y = MISS_BMA.F9)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F9, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
             color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.F9, na.rm = TRUE)),
             color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.1),
             color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per locus", y = "% missing data") +
  theme_standard

m3 <- multiplot(p1, p2, p3, p4, p5, p6, cols=2)

Data set contains 23040 SNP sites and 402 individuals.

Filter 11: Excess heterozygosity

Identify SNPs with more than 0.5 heterozygosity and significant.

Distribution of observed heterozygosity.

Identify loci with heterozygosity > 0.5, then correct p-values for multiple comparisons using Benjamini-Hochberg method.

Remove SNPs with excess heterozygosity and contigs with more than one SNP w/excess heterozygosity.

Visualize stats:

Data set contains 16831 SNP sites and 402 individuals.

Filter 12: Filter LQ individuals

Compare mean depth and number of sites called per individual.

Use genotype depth file to identify individuals with high variance in read depth across loci.

Compare distribution of depth.

Compare distribution of depth of individuals grouped by library.

Compare distribution of genotype depths (across all individuals).

Identify variance in depth w/in individuals.

Compare depth, missing data and individual heterozygosity levels.


imiss <- read_table2("data/VCF/BMA.F11.imiss") %>%
  select(INDV, N_DATA, F_MISS)

istats <- left_join(idepth, imiss)

Fis <- read_table2("data/VCF/BMA.F11.het") %>%
  select(-N_SITES)

istats <- left_join(istats, Fis)

p1 <- ggplot(istats, aes(x = MEAN, y = F_MISS, fill = `F`)) +
  geom_point(shape = 21, size = 2, color = "black") +
  scale_fill_viridis(direction = 1, option = "viridis",
                     name = 'Fis', discrete = FALSE) +
  theme_standard

p2 <- ggplot(istats, aes(x = COEFF_VAR, y = MEAN, fill = F_MISS)) +
 geom_point(shape = 21, size = 2, color = "black") +
  scale_fill_viridis(direction = -1, option = "viridis",
                     name = '% missing', discrete = FALSE) +
  theme_standard

p3 <- ggplot(istats, aes(x = `O(HOM)`, y = MEAN, fill = F_MISS)) +
  geom_point(shape = 21, size = 2, color = "black") +
  scale_fill_viridis(direction = -1, option = "viridis",
                     name = 'mean read depth', discrete = FALSE) +
  theme_standard

p4 <- ggplot(istats, aes(x = MEAN)) +
  geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
  theme_standard

p5 <- ggplot(istats, aes(x = `F`, y = MEAN, fill = F_MISS)) +
  geom_point(shape = 21, size = 2, color = "black") +
  scale_fill_viridis(direction = -1, option = "viridis",
                     name = '% missing', discrete = FALSE) +
  theme_standard

p6 <- ggplot(istats, aes(x = `F`, y = COEFF_VAR, fill = F_MISS)) +
  geom_point(shape = 21, size = 2, color = "black") +
  scale_fill_viridis(direction = -1, option = "viridis",
                     name = '% missing', discrete = FALSE) +
  theme_standard

p7 <- ggplot(istats, aes(x = `F`, y = RATIO_MEAN_MEDIAN, fill = F_MISS)) +
  geom_point(shape = 21, size = 2, color = "black") +
  scale_fill_viridis(direction = -1, option = "viridis",
                     name = '% missing', discrete = FALSE) +
  scale_y_continuous(limits = c(0.8, 4)) +
  theme_standard

p8 <- ggplot(istats, aes(x = F_MISS)) +
  geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
  theme_standard


m14b <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, cols=2)

Flag low quality individuals

Filter 13: Missing data by sample location


vcftools --vcf data/VCF/temp/BMA.F11.recode.vcf --out data/VCF/temp/BMA.F12 --remove data/VCF/F12_LQ.indv --recode --recode-INFO-all

# Campeche
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/CAMP --keep data/VCF/CAMP.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/CAMP.recode.vcf --out data/VCF/CAMP --missing-site

# Chandeleur Sound
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/CS --keep data/VCF/CS.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/CS.recode.vcf --out data/VCF/CS --missing-site

# Corpus Christi Bay
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/CC --keep data/VCF/CC.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/CC.recode.vcf --out data/VCF/CC --missing-site

# Florida Atlantic
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/FLA --keep data/VCF/FLA.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/FLA.recode.vcf --out data/VCF/FLA --missing-site

# Florida Gulf South
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/FLGS --keep data/VCF/FLGS.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/FLGS.recode.vcf --out data/VCF/FLGS --missing-site

# Florida Gulf North 
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/FLGN --keep data/VCF/FLGN.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/FLGN.recode.vcf --out data/VCF/FLGN --missing-site

# Louisiana
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/LA --keep data/VCF/LA.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/LA.recode.vcf --out data/VCF/LA --missing-site

# Mississippi Sound 
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/MISS --keep data/VCF/MISS.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/MISS.recode.vcf --out data/VCF/MISS --missing-site

# Mobile Bay
vcftools --vcf data/VCF/temp/BMA.F12.recode.vcf --out data/VCF/temp/MB --keep data/VCF/MB.ind  --recode --recode-INFO-all
vcftools --vcf data/VCF/temp/MB.recode.vcf --out data/VCF/MB --missing-site

Compare missing data per sample region:

identify loci with high missing data in each sample location (> 15 % missing data in a given location).

Remove loci from data set:

Compare stats:


# load stats files ----
ind_stats_F13 <- read.ind.stats(dir = "data/VCF", vcf = "BMA.F13") %>%
  separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE, extra = "merge")

loc_stats_F13 <- read.loc.stats(dir = "data/VCF", vcf = "BMA.F13")

# plot missing data per indv ----
p1 <- ggplot(ind_stats_F13, aes(x = MISS_BMA.F13)) +
  geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.25),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "missing data per indv") +
  theme_standard

# plot read depth per indv ----
p2 <- ggplot(ind_stats_F13, aes(x = MEAN_DEPTH_BMA.F13)) +
  geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per indv") +
  theme_standard

# plot depth vs missing ----
p3 <- ggplot(ind_stats_F13, aes(x = MEAN_DEPTH_BMA.F13, y = MISS_BMA.F13)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.25),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per indv", y = "% missing data") +
  theme_standard

# plot Fis per indv ----
p4 <- ggplot(ind_stats_F13, aes(x = Fis_BMA.F13)) +
  geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(Fis_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv") +
  theme_standard

# plot Fis vs missing data per indv ----
p5 <- ggplot(ind_stats_F13, aes(x = Fis_BMA.F13, y = MISS_BMA.F13)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(Fis_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.25),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv", y = "% missing data") +
  theme_standard

# plot Fis vs mean depth per indv ----
p6 <- ggplot(ind_stats_F13, aes(x = Fis_BMA.F13, y = MEAN_DEPTH_BMA.F13)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(Fis_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv", y = "mean depth per indv") +
  theme_standard


# plot distribution missing data per locus ----
p7 <- ggplot(loc_stats_F13, aes(x = MISS_BMA.F13)) +
  geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.1),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "% missing data per locus") +
  theme_standard

# plot distribution mean read depth ----
p8 <- ggplot(loc_stats_F13, aes(x = MEAN_DEPTH_BMA.F13)) +
  geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per locus") +
  theme_standard

# plot read depth vs missing data ----
p9 <- ggplot(loc_stats_F13, aes(x = MEAN_DEPTH_BMA.F13, y = MISS_BMA.F13)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.F13, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.1),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per locus", y = "% missing data") +
  theme_standard

# plot depth vs SNP quality ----
site_qual <- read.table("data/VCF/BMA.F13.lqual", 
                        header = TRUE, stringsAsFactors = FALSE) %>%
  mutate(PROB = 10^(-QUAL/10))

temp <- data.frame(loc_stats_F13$MEAN_DEPTH_BMA.F13, site_qual$QUAL) %>%
  rename(depth = loc_stats_F13.MEAN_DEPTH_BMA.F13, qual = site_qual.QUAL)

p10 <- ggplot(temp, aes(x = depth, y = qual)) +
  geom_point(size = 1) +
  geom_vline(aes(xintercept = mean(depth, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(qual, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per locus", y = "SNP quality") +
  theme_standard

# plot number of SNPs per contig vs. mean depth ----
temp <- loc_stats_F13 %>%
  count(CHR)

p11 <- left_join(temp, loc_stats_F13) %>%
  ggplot() +
  geom_point(aes(x = n, y = MEAN_DEPTH_BMA.F13)) +
  labs(x = "number of SNPs per contig", y = "mean depth") +
  theme_standard

# plot no of SNPs per locus ----
p12 <- loc_stats_F13 %>%
  count(CHR) %>%
  ggplot(aes(x = n)) +
  geom_histogram(binwidth = 1, color = "black", fill = "darkorange") + 
  labs(x = "number of SNPs per locus") +
  theme_standard

m15 <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, cols=2)

Compare number of contigs vs number of SNPs.

[1] 14682
[1] 6048

Mean number of SNPs per contig is 64.1135371.

Final thresholds values for filtered data set BMA:

  • minimum sequence quality (minQ): 20
  • minimum genotype quality (minGQ): 20
  • minimum genotype call rate per locus (geno): 90%
  • minimum genotype depth (minD): 5
  • maximum missing data per individual (missInd): 25%
  • mean minimum depth per locus (m-minD): 15
  • mean maximum depth (m-minD): 300
  • dDocent filters run for allelic balance, mapping quality, strandedness and paired status, depth/quality ratio
  • Indels removed from data set
  • minimum genotype call rate by population: 85%

Data set contains 14682 SNP sites on 229 and 384 individuals.

Haplotyping

Prep for haplotyping

Create list of individuals retained in final vcf file:

Change so that new file is printed into Haplotyping/temp folder

Use BMA-BMA.individuals to create popmap as a tab-separated file of individuals and their population designation, with one individual per line (make sure UNIX format). This file is needed to write the genepop file, if not provided the script will run through the process but not write a genepop file and place into same folder rad_haplotyper.pl will be run from.

Place all necessary files in data/Haplotyping/temp directory (bam, fastq, reference.fasta, vcf-file)

Haplotype filtering

Overview of haplotyping success

Comparison of the number of loci that were filtered due to excess number of missing data or suspected paralogs during the haplotyping process to those that passed. Haplotyer was run without any threshold values (other than default values). The genepop file only contains loci that passed haplotyping stage.

Remove filtered loci from data set.

5957 loci passed haplotyping process.

Data set contains 384 individuals:

Identify threshold values to filter data set

Proportion of individuals haplotyped

Flag loci successfully haplotyped in < 90% of individuals.

136 loci were flagged as genotype call rate < 0.9.

Possible paralogs per locus

Loci are flagged as possible paralogs for an individuals when more than the expected number of haplotypes based on the SNP genotype call (homozygote, heterozygote) are detected.

1 % of individuals: 3.84 5 % of individuals: 19.2

Flag loci that are flagged as potential paralogs in 5 or more individuals. 4

176 loci were flagged as possible paralogs.

Number of SNPs & Haplotypes per locus

Each locus varies in the number of SNPs detected which determines the number of haplotypes expected in that population.

Filtering loci based on number of SNPs contained on that locus could bias the data set as loci with high recombination may be removed. On the other hand, assuming an approximate length of 250 bp loci with more than 25 SNPs would mean that 10% of bases are a polymorphisms.

Identify number of haplotypes loci with > 35 SNP sites.

0 loci were flagged.

Assuming that mutation is the only mechanism resulting in new haplotypes, the maximum expected number of haplotypes per locus is number of SNPs N + 1.


p1 <- ggplot(hap_stats, aes(x = Haplotypes)) +
  geom_histogram(binwidth = 1, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(Haplotypes, na.rm = TRUE)),
                 color = "darkred", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = quantile(Haplotypes, .99, na.rm = TRUE)),
                 color = "darkred", linetype = "dashed", size = 1) +
  labs(x = "# haplotypes per locus", y = "# loci") +
  theme_standard

temp <- hap_stats %>%
  select(Locus, Sites, Haplotypes, Prop_Haplotyped, Low_Cov.Geno_Err, Poss_Paralog) %>%
  mutate(exp_sites = Sites + 1) %>%
  mutate(xtra = Haplotypes - Sites)

p2 <- ggplot(temp, aes(x = Sites, y = Poss_Paralog)) +
  geom_point() +
  geom_hline(yintercept = 5, color = "darkblue", linetype = "dashed", size = 1) +
  geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "# SNP sites per locus", y = "possible paralogs") +
  theme_standard

p3 <- ggplot(temp, aes(x = Sites, y = xtra)) +
  geom_point() +
  geom_hline(yintercept = 10, color = "darkblue", linetype = "dashed", size = 1) +
  geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "# SNP sites per locus", y = "# extra haplotypes") +
  theme_standard

p4 <- ggplot(temp, aes(x = xtra, y = Prop_Haplotyped)) +
  geom_point(size = 1) +
  geom_hline(yintercept = 0.9, color = "darkblue", linetype = "dashed", size = 1) +
  geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "# extra haplotypes", y = "proportion of indv haplotyped") +
  theme_standard

p5 <- ggplot(temp, aes(x = xtra, y = Low_Cov.Geno_Err)) +
  geom_point(size = 1) +
  geom_hline(yintercept = 5, color = "darkblue", linetype = "dashed", size = 1) +
  geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "# extra haplotypes", y = "potential genotyping error") +
  theme_standard

p6 <- ggplot(temp, aes(x = xtra, y = Poss_Paralog)) +
  geom_point(size = 1) +
  geom_hline(yintercept = 5, color = "darkblue", linetype = "dashed", size = 1) +
  geom_vline(xintercept = 25, color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "# extra haplotypes", y = "possible paralogs") +
  theme_standard

m21 <- multiplot(p1, p2, p3, p4, p5, p6, cols = 2)

Again, removing loci with unexpectedly high numbers of haplotypes may bias the data set, as loci with e.g. high recombination may be removed from the data set.

0 loci were flagged for excessive number of haplotypes compared to the number of SNPs at that locus.

Low Coverage/Genotyping Error

After combining SNPs on the same contig during the haplotyping process, it is possible to observe fewer than the expected number of haplotypes based on the genotype call (heterozygote/homozygote). When this occurs, that genotype is coded as missing. For each locus the number of individuals for which is it flagged as a potential a potential genotyping error or suffering from null alleles due to low coverage detected for a given locus is recorded.

Loci with pronounced patterns of genotyping error likely due to low coverage will have low success rate for genotyping, i.e. they will be caught in missing data filters. Coverage issues are likely genotype specfic; previous filters have targeted loci and individuals with high variance in coverage and suspect genotpes have been coded as missing, i.e. this filter need not be very conservative, regardless, loci that are repeatedly being flagged as problematic should be removed.

183 loci were flagged as potentially affected by genotyping error.

Flag problematic individuals

Loci that are not successfully haplotyped in an individual due to missing data, complex locus, haplotyped genotype is higher/lower than SNP haplotype in a given individual are coded as missing for that individual. Problematic individual can be identified as having a high proportion of missing data.

Individuals with low proportion of successfully haplotyped loci

Problem individuals can be identified by choosing a cut-off value for the minium proportion of sucessfully haplotyped loci and excluding individuals below that threshold value. Removing loci with low haplotyping success with decrease the amount of missing data. Therefore, final missing data cut-offs should be applied after removing those loci from the data set, though it is important to flag potentially problematic individuals based on their haplotyping stats at this point.

Possible paralogs per individual

Individuals with high proportion of loci flagged as possible paralogs should be flagged as potential problem individuals.

Cut-off for individuals with loci flagged paralogs in > 1% of loci is 59.57.

The highest number of flagged loci in an individuals is 81, which is equivalent to 1.36% of loci.

Individuals with high proportion of potential allele dropout/genotyping error

Remove individuals with high proportion of loci that have been flagged as potential allele dropouts/genotyping error.

The highest number of flagged loci in an individuals is 110, which is equivalent to 1.85% of loci.

Filter flagged loci and individuals as necessary

Load genepop file with haplotyped loci.


 Converting data from a Genepop .gen file to a genind object... 


File description:  BMA.gen 

...done.
/// GENIND OBJECT /////////

 // 384 individuals; 5,957 loci; 20,898 alleles; size: 35.6 Mb

 // Basic content
   @tab:  384 x 20898 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 1-25)
   @loc.fac: locus factor for the 20898 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: read.genepop(file = "data/Haplotyping/BMA.gen", ncode = 3L, quiet = FALSE)

 // Optional content
   @pop: population of each individual (group size range: 384-384)

Remove flagged loci and individuals.

/// GENIND OBJECT /////////

 // 380 individuals; 5,621 loci; 18,801 alleles; size: 31.8 Mb

 // Basic content
   @tab:  380 x 18801 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 1-25)
   @loc.fac: locus factor for the 18801 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: .local(x = x, i = i, j = j, drop = drop)

 // Optional content
   @pop: population of each individual (group size range: 380-380)

Compare duplicate individuals


# extract genotype matrix
df <- genind2df(gen,
                usepop = TRUE,
                sep = ":", oneColPerAll = FALSE) %>%
  select(-pop) %>%
  rownames_to_column()

# create list of duplicates
pairs <- list()

# input each set of duplicates as a vector of a list
pairs[[1]] <- c("BMA_3B-E12_MS-37", "BMA_2A-C01_MS-57")
pairs[[2]] <- c("BMA_1A-C01_CCGN-001", "BMA_1A-D02_CCGN01")
pairs[[3]] <- c("BMA_1A-H04_CC02-35",   "BMA_2B-B09_CC-35")
pairs[[4]] <- c("BMA_3B-H02_MS26", "BMA_3B-D01_MS26")
pairs[[5]] <- c("BMA_2B-H02_MB06", "BMA_1B-E06_MB-06")
pairs[[6]] <- c("BMA_1B-G11_CC-08", "BMA_1A-H03_CC02-08")
pairs[[7]] <- c("BMA_3B-H03_BM027", "BMA_3B-A07_BM027")
pairs[[8]] <- c("BMA_1B-C04_MS-21", "BMA_2A-C05_MS-61")
pairs[[9]] <- c("BMA_2B-H01_CS3", "BMA_1A-B03_CS-03")
pairs[[10]] <- c("BMA_3B-E11_MS-36", "BMA_1B-C12_MS-56")
pairs[[11]] <- c("BMA_2A-C07_MS-63", "BMA_1B-C06_MS-23")
pairs[[12]] <- c("BMA_2B-B01_CC-12", "BMA_3A-A02_CC-12")
pairs[[13]] <- c("BMA_2B-G05_BMAR-03", "BMA_3B-E12_BMAR-02")


# create empty list for genotype error (discordant loci)
genoerror <- list()

# create empty vector for duplicates (retains first indv in pair)
dup <- character()

# identify discordant genotypes for each set of duplicates
for (p in pairs){

# select duplicates from genotype matrix
geno <- df %>%
  filter(rowname %in% p) %>%
  select(-rowname)

# compare genotypes
comp <- (t(geno))

contigs <- as.data.frame(comp) %>%
  rownames_to_column(var = "LOCUS") %>%
  mutate(V1 = as.character(V1),
         V2 = as.character(V2)) %>%
  filter(V1 != V2)

# write vector with first individual in pair
ind <- p[1]

dup <- c(dup, ind)

genoerror[[ind]] <- contigs

}

# if it throws error object V1 or V2 not found it means one or more of the samples names are not correct or no longer in data set after filtering

# combine into one dataframe
genoerror <- ldply(genoerror, data.frame) %>%
  rename(DUP1 = `.id`,
         GENO_INDV1 = V1,
         GENO_INDV2 = V2)

write_delim(genoerror, "results/haplotyped.genoerror", delim = "\t")

Compare genotype depth for discordant loci:

Determine number of times discordant genotype is due to heterozygote/homozygote.

Compare number of discordant genotype calls per duplicate set.

Identify loci consistently affected by genotyping error

Remove flagged loci and one individual per pair.

/// GENIND OBJECT /////////

 // 367 individuals; 5,621 loci; 18,801 alleles; size: 30.9 Mb

 // Basic content
   @tab:  367 x 18801 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 1-25)
   @loc.fac: locus factor for the 18801 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)

 // Optional content
   @pop: population of each individual (group size range: 367-367)

12708 loci were removed as potentially affected by genotyping error.

Relatedness & Inbreeding

Create input file fore related package.

Calculate pairwise relatedness according to Lynch & Ritland 1999; uses inbreeding estimates for each individuals to estimate relatedness.

Distribution of levels of pairwise relatedness:

Distribution of levels of homozygosity:

Heterozygosity and HWE

Generate summary statistics

Compare observed (Ho) and expected (He) heterozygosity for all individuals across all populations.

Identify loci that are now monomorphic and remove from data set:

/// GENIND OBJECT /////////

 // 367 individuals; 5,590 loci; 18,768 alleles; size: 30.9 Mb

 // Basic content
   @tab:  367 x 18768 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 2-25)
   @loc.fac: locus factor for the 18768 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)

 // Optional content
   @pop: population of each individual (group size range: 20-52)
   @strata: a data frame with 5 columns ( LIB_ID, SP, WELL, SAMPLE_ID, POP )

Expected vs observed heterozygosity across all populations.

Compare distribution of observed heterozygosity (Ho) in each putative population:

Compare distribution of expected heterozygosity He, (within cluster diversity) in each putative population:

Comparison of oberved vs. heterozygosity within each population:

Test for deviations from Hardy-Weinberg equilibrium within each group (POP level):

Format output and view results:

Distribution of number of times loci are out of HWE

Remove loci out of HWE in 5 or more populations:

/// GENIND OBJECT /////////

 // 367 individuals; 5,554 loci; 18,611 alleles; size: 30.7 Mb

 // Basic content
   @tab:  367 x 18611 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 2-25)
   @loc.fac: locus factor for the 18611 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)

 // Optional content
   @pop: population of each individual (group size range: 20-52)
   @strata: a data frame with 7 columns ( LIB_ID, SP, WELL, SAMPLE_ID, POP, REGION, ... )

Final data set

Write files with filtered data set:

Write files with individuals and Contigs still contained in data set and use to filter vcf file.

Expected 4 pieces. Missing pieces filled with `NA` in 329 rows [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, ...].Expected 2 pieces. Missing pieces filled with `NA` in 38 rows [10, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 163, 164, 165, 166, 167, 168, 169, 170, 171, ...].
Error in filter(ind_stats_F14, INDV %in% keepind$LIB_ID) : 
  object 'ind_stats_F14' not found

Write vcf file and 012 format:

Compare stats for final filtered data set:


# load stats files ----
ind_stats_fil <- read.ind.stats(dir = "data/VCF", vcf = "BMA.fil") %>%
  separate(INDV, into = c("SP", "LIB", "SAMPLE_ID"), sep = "_", remove = FALSE)

loc_stats_fil <- read.loc.stats(dir = "data/VCF/", vcf = "BMA.fil")

View(ind_stats_fil)
View(hap_ind_stats)

# plot missing data per indv ----
p1 <- ggplot(ind_stats_fil, aes(x = MISS_BMA.fil)) +
  geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.25),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "missing data per indv") +
  theme_standard

# plot Fis per indv ----
p2 <- ggplot(ind_stats_fil, aes(x = Fis_BMA.fil)) +
  geom_histogram(binwidth = .01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(Fis_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv") +
  theme_standard

# plot read depth per indv ----
p3 <- ggplot(ind_stats_fil, aes(x = MEAN_DEPTH_BMA.fil)) +
  geom_histogram(binwidth = 10, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per indv") +
  theme_standard

# plot depth vs missing ----
p4 <- ggplot(ind_stats_fil, aes(x = MEAN_DEPTH_BMA.fil, y = MISS_BMA.fil)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.25),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per indv", y = "% missing data") +
  theme_standard

# plot Fis vs missing data per indv ----
p5 <- ggplot(ind_stats_fil, aes(x = Fis_BMA.fil, y = MISS_BMA.fil)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(Fis_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.25),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv", y = "% missing data") +
  theme_standard

# plot Fis vs mean depth per indv ----
p6 <- ggplot(ind_stats_fil, aes(x = Fis_BMA.fil, y = MEAN_DEPTH_BMA.fil)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(Fis_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "Fis per indv", y = "mean depth per indv") +
  theme_standard

# plot distribution missing data per locus ----
p7 <- ggplot(ind_stats_fil, aes(x = MISS_BMA.fil)) +
  geom_histogram(binwidth = 0.01, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 0.1),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "% missing data per locus") +
  theme_standard

# plot distribution mean read depth ----
p8 <- ggplot(loc_stats_fil, aes(x = MEAN_DEPTH_BMA.fil)) +
  geom_histogram(binwidth = 5, color = "black", fill = "darkorange") +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean read depth per locus") +
  theme_standard

# plot read depth vs missing data ----
p9 <- ggplot(loc_stats_fil, aes(x = MEAN_DEPTH_BMA.fil, y = MISS_BMA.fil)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(MEAN_DEPTH_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(MISS_BMA.fil, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 0.1),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per locus", y = "% missing data") +
  theme_standard

# plot no of SNPs per locus ----
p10 <- loc_stats_fil %>%
  count(CHR) %>%
  ggplot(aes(x = n)) +
  geom_histogram(binwidth = 1, color = "black", fill = "darkorange") + 
  labs(x = "number of SNPs per locus") +
  theme_standard

temp <- loc_stats_fil %>%
  count(CHR)

# plot number of SNPs per contig vs. mean depth ----
p11 <- left_join(temp, loc_stats_fil) %>%
  ggplot() +
  geom_point(aes(x = n, y = MEAN_DEPTH_BMA.fil)) +
  labs(x = "number of SNPs per contig", y = "mean depth") +
  theme_standard

# plot depth vs SNP quality ----
site_qual <- read.table("data/VCF/BMA.fil.lqual", 
                        header = TRUE, stringsAsFactors = FALSE) %>%
  mutate(PROB = 10^(-QUAL/10))

temp <- data.frame(loc_stats_fil$MEAN_DEPTH_BMA.fil, site_qual$QUAL) %>%
  rename(depth = loc_stats_fil.MEAN_DEPTH_BMA.fil, qual = site_qual.QUAL)

p12 <- ggplot(temp, aes(x = depth, y = qual)) +
  geom_point(size = 1) +
  geom_vline(aes(xintercept = mean(depth, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = mean(qual, na.rm = TRUE)),
                 color = "red", linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = 20),
                 color = "darkblue", linetype = "dashed", size = 1) +
  labs(x = "mean depth per locus", y = "SNP quality") +
  theme_standard

mfil <- multiplot(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, cols=2)

LS0tCnRpdGxlOiAiR2Vub3R5cGluZyBHYWZmdG9wc2FpbCBjYXRmaXNoIGRhdGEgc2V0IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBoaWdobGlnaHQ6IGthdGUKICAgIHRoZW1lOiBmbGF0bHkKICAgIHRvYzogeWVzCi0tLQoKYGBge3IgbG9hZCBsaWJyYXJpZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cgpzb3VyY2UoInNjci9saWJyYXJpZXMuUiIpCnNvdXJjZSgic2NyL2dncGxvdC5SIikKc291cmNlKCJzY3IvVkNGZmlsdGVyc3RhdHMuUiIpCnNvdXJjZSgic2NyL0hhcGxvdHlwUi5SIikKc291cmNlKCJzY3IveHRyYWZ1bmN0aW9ucy5SIikKc291cmNlKCJzY3IvZ2VuaW5kLlIiKQoKCnBvcHMgPC0gYygiRkxBIiwgCiAgICAgICAgICAiRkxHUyIsICJGTEdOIiwgCiAgICAgICAgICAiTUIiLCAiTUlTUyIsICJDUyIsICJMQSIsIAogICAgICAgICAgIkNDIiwgCiAgICAgICAgICAiQ0FNUCIpCgpjb2xfcG9wcyA8LSBjKCJjaGFydHJldXNlNCIsIAogICAgICAgICAgICAgICJkb2RnZXJibHVlNCIsICJzdGVlbGJsdWUxIiwgCiAgICAgICAgICAgICAgImZpcmVicmljayIsICJvcmFuZ2VyZWQzIiwgImRhcmtvcmFuZ2UiLCAiZ29sZCIsCiAgICAgICAgICAgICAgImRhcmtzbGF0ZWdyZXkxIiwKICAgICAgICAgICAgICAicHVycGxlMyIpCgpyZWcgPC0gYygiU1dBVEwiLCAiRUdVTEYiLCAiQ0dVTEYiLCAiV0dVTEYiLCAiU0dVTEYiKQoKY29sX3JlZ3MgPC0gYygiY2hhcnRyZXVzZTQiLCAiZG9kZ2VyYmx1ZTQiLCAib3JhbmdlcmVkMyIsICJkYXJrc2xhdGVncmF5MSIsICJwdXJwbGUzIikKCm9jZSA8LSBjKCJBVEwiLCAiR1VMRiIpCgpjb2xfb2NlIDwtIGMoImNoYXJ0cmV1c2U0IiwgImRhcmtzbGF0ZWdyYXkxIikKCmBgYAoKIyBSZWFkIG1hcHBpbmcKCiMjIE1hcCByZWFkcwoKQW55IHJlbmFtaW5nIG9mIGZpbGVzIG5lZWRzIHRvIGhhcHBlbiBiZWZvcmUgYGZhc3RxYC1maWxlcyBhcmUgbWFwcGVkLiBUaGUgcG9wdWxhdGlvbiBkZXNpZ25hdGlvbiAoYmVmb3JlIHVuZGVyc2NvcmUpIGlzIHVzZWQgYnkgYEZyZWVCYXllc2AgdG8gY2FsbCBTTlBzIHNvIGl0IGlzIGltcG9ydGFudCB0aGF0IHBvcHVsYXRpb24gZGVzaWduYXRpb24gbWFrZSBiaW9sb2dpY2FsIHNlbnNlLgoKVmFsdWVzIGNob3NlbiBmb3IgcmVkdWNlZCByZXByZXNlbnRhdGlvbiByZWZlcmVuY2U6CgoqICoqYyoqID0gMC44CiogKipLMSoqID0gNQoqICoqSzIqKiA9IDIKClRyYW5zZmVyIGNvcHkgb2YgYHJlZmVyZW5jZS5mYXN0YWAgYW5kIGFzc29jaWF0ZWQgZmlsZXMgUmVmZXJlbmNlIGNvbnN0cnVjdGVkIHVzaW5nICpjID0gMC44KiwgKksxID0gNSosIGFuZCAqSzIgPSAyKi4gaW50byBlYWNoIGRpcmVjdG9yeSBjb250YWluaW5nIGRlbXVsdGlwbGV4ZWQgYW5kIHF1YWxpdHkgdHJpbW1lZCBkYXRhL1NFUQoKUnVuIGBkRG9jZW50YCBmcm9tIHdpdGhpbiBlYWNoIExpYnJhcnkgZGlyZWN0b3J5IHRvIG1hcCByZWFkcyB0byBgcmVmZXJlbmNlLmZhc3RhYC4KCmBgYHtiYXNofQoKIyBnbyB0byByZWZlcmVuY2UgcGFyZW50IGRpcmVjdG9yeQpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9TRVEvCgojIGxvb3Agb3ZlciBhbGwgcmVmZXJlbmNlIGNyZWF0aW9uIGZvbGRlcnMKZm9yIGQgaW4gQk1BKgoKZG8KCiAgICAoY3AgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvUkVGL1JFRjVfMi9yZWZlcmVuY2UuKiAkZC8pCiAgICAKZG9uZQoKYGBgCgpXcml0ZSBjb25maWd1cmF0aW9uIGZpbGUgdG8gcnVuIGREb2NlbnQgaW4gZWFjaCByZWZlcmVuY2UgZGlyZWN0b3J5LgoKYGBge3J9CgojIHBhcmFtZXRlcnMgZm9yIHNoZWxsIHNjcmlwdCAtLS0tCgojIGNvcnJlY3QgbnVtYmVyIG9mIGluZGl2aWR1YWxzCmluZCA8LSAieWVzIgoKIyBudW1iZXIgb2YgcHJvY2Vzc29ycwpwcm9jZXNzb3JzIDwtICIyNSIKCiMgcXVhbGl0eSB0cmltIG5lZWRlZAp0cmltIDwtICJubyIKCiMgcGVyZm9ybSByZWZlcmVuY2UgYXNzZW1ibHkKYXNzZW1ibHkgPC0gIm5vIgoKIyByZWFkIG1hcHBpbmcgcmVxdWlyZWQKbWFwIDwtICJ5ZXMiCgojIGN1c3RvbSB2YWx1ZXMgZm9yIG1hcHBpbmcKbWFwX3BhcmFtIDwtICJ5ZXMiCgojIG1hdGNoIHNjb3JlCkEgPC0gIjEiCgojIG1pc21hdGNoIHNjb3JlCkIgPC0gIjMiCgojIGdhcCBwZW5hbHR5Ck8gPC0gIjUiCgojIFNOUCBjYWxsaW5nIHJlcXVpcmVkCnNucCA8LSAibm8iCgojIGVtYWlsIGFkZHJlc3MKZW1haWwgPC0gInNoYW5ub24uai5vbGVhcnlAZ21haWwuY29tIgoKIyBkZWZpbmUgcGF0aHMvZGlyZWN0b3JpZXMgLS0tLQoKIyBwYXRoIHRvIHBhcmVudCBkaXJlY3RvcnkgZm9yIHJlZmVyZW5jZXMKcGF0aCA8LSAiL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvU0VRIgoKIyBzZXF1ZW5jZSBmb2xkZXJzCmRpciA8LSBjKCJCTUEtMSIsICJCTUEtMiIsICJCTUEtMyIpCgojIHdyaXRlIHNoZWxsIHNjcmlwdHMgaW4gZWFjaCBkaXJlY3RvcnkgLS0tLQpmb3IoZCBpbiBkaXIpewogIAogICMgd3JpdGUgc2hlbGwgc2NyaXB0CiAgcCA8LSBmaWxlLnBhdGgocGF0aCwgZCwgImREb2NlbnRfbWFwLnNoIikKICAKICBjb24gPC0gZmlsZShwLCBvcGVuID0gInd0IikKICAKICB3cml0ZUxpbmVzKGdsdWUoImREb2NlbnQgPDxPdmVyISAKICAgICAgICAgICAgICAgICAge2luZH0gCiAgICAgICAgICAgICAgICAgIHtwcm9jZXNzb3JzfSAKICAgICAgICAgICAgICAgICAge3RyaW19IAogICAgICAgICAgICAgICAgICB7YXNzZW1ibHl9IAogICAgICAgICAgICAgICAgICB7bWFwfSAgCiAgICAgICAgICAgICAgICAgIHttYXBfcGFyYW19IAogICAgICAgICAgICAgICAgICB7QX0gCiAgICAgICAgICAgICAgICAgIHtCfSAKICAgICAgICAgICAgICAgICAge099IAogICAgICAgICAgICAgICAgICB7c25wfSAKICAgICAgICAgICAgICAgICAge2VtYWlsfSAKICAgICAgICAgICAgICAgICAgT3ZlciEiKSwgY29uKQogIAogIGNsb3NlKGNvbikKICAKfQoKYGBgCgpFeGVjdXRlIGBkRG9jZW50YCBmcm9tIHdpdGhpbiBlYWNoIHJlZmVyZW5jZSBmb2xkZXIgdG8gaW5pdGlhdGUgYSBydW4gdG8gbWFwIGluZGl2aWR1YWxzIHRvIHJlZHVjZWQgcmVwcmVzZW50YXRpb24gcmVmZXJlbmNlIGFuZCBjYWxsIFNOUHMuCgpgYGB7YmFzaH0KCiMgZ28gdG8gc2VxdWVuY2UgcGFyZW50IGRpcmVjdG9yeQpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9TRVEvCgojIGxvb3Agb3ZlciBhbGwgcmVmZXJlbmNlIGNyZWF0aW9uIGZvbGRlcnMKZm9yIGQgaW4gQk1BLSoKCmRvCgogICAgKGNkICIkZCIgJiYgY2htb2QgNzU1IGREb2NlbnRfbWFwLnNoICYmIC4vZERvY2VudF9tYXAuc2gpCiAgICAKZG9uZQoKYGBgCgojIyBRQS9RQyByZWFkIG1hcHBpbmcKCiMjIyBRdWVyeSBtYXBwaW5nIHN0YXRpc3RpY3MKCkR1cmluZyB0aGUgbWFwcGluZyBzdGFnZSwgYGREb2NlbnRgIGNhbGxzIGBCV0FgIHRvIG1hcCByZWFkcyBmcm9tIHRoZSBpbmRpdmlkdWFscyBpbiB0aGUgZm9sZGVyIHRvIHRoZSBnZW5lcmF0ZWQgcmVkdWNlZCByZXByZXNlbnRhdGlvbiByZWZlcmVuY2UgYW5kIGNyZWF0ZSBhIGAtUkcuYmFtYC1maWxlIGZvciBlYWNoIGluZGl2aWR1YWwuIFRoZSBzZWNvbmQgY29sdW1uIG9mIGEgQkFNIChvciBTQU0pIGZpbGUgY29udGFpbnMgRkxBR3Mgd2l0aCBiaW5hcnkgZW5jb2RlZCBpbmZvcm1hdGlvbiBvbiBtYXBwaW5nIHF1YWxpdHksIHBhaXJlZG5lc3MgZXRjLiB0aGF0IGNhbiBiZSB1c2VkIHRvIGNvbXBhcmUgdGhlIG1hcHBpbmcgZWZmaWNpZW5jeSB0byB0aGUgcmVkdWNlZCByZXByZXNlbnRhdGlvbiByZWZlcmVuY2UuCgpUaGUgbnVtYmVyIG9mIHJlYWRzIG1hcHBlZCBjYW4gYmUgY291bnRlZCB1c2luZyBgc2FtdG9vbHMgaWR4c3RhdHMgPGFsbi1SRy5iYW0+YCB3aGljaCByZXRyaWV2ZXMgc3RhdHMgZnJvbSB0aGUgYmFtLWZpbGUuIFRoZSBvdXRwdXQgaXMgVEFCLWRlbGltaXRlZCBmaWxlIHdpdGggZWFjaCBsaW5lIGNvbnNpc3Rpbmcgb2YgdGhlIHJlZmVyZW5jZSBzZXF1ZW5jZSBuYW1lLCBzZXF1ZW5jZSBsZW5ndGgsICMgbWFwcGVkIHJlYWRzIGFuZCAjIHVubWFwcGVkIChlbXB0eSkgcmVhZHMuIEluIGFkZGl0aW9uLCBgc2FtdG9vbHNgIGNhbiBhbHNvIGJlIGJlIHVzZWQgdG8gcXVlcnkgYHNhbXRvb2xzIGZsYWdzdGF0IGZpbGUuYmFtYCB3aGljaCByZXR1cm5zIGFuIG91dHB1dCBjb250YWluaW5nIHRoZSBudW1iZXIgb2YgcmVhZHMgZm9yIHdoaWNoIGVhY2ggZmxhZyBpcyB0cnVlLgoKZERvY2VudCBjcmVhdGVzIGEgZmlsZSBjYWxsZWQgYGJhbWxpc3QubGlzdGAgY29udGFpbmluZyBhbGwgdGhlIGJhbSBmaWxlcyB0aGF0IHdlcmUgZ2VuZXJhdGVkIGR1cmluZyByZWFkIG1hcHBpbmcgaW4gYGREb2NlbnRgIHVzaW5nIGBCV0FgLiBXcml0ZSBzY3JpcHQgdG8gZ2F0aGVyIGZsYWdzdGF0cyBmcm9tIGFsbCBgYmFtYC1maWxlcy4KCmBgYHtyIGZsYWdzdGF0cyBzY3JpcHR9CgojIFNlcXVlbmNlIGZvbGRlcnMKU0VRIDwtIGMoIkJNQS0xIiwgIkJNQS0yIiwgIkJNQS0zIikKCiMgd3JpdGUgc2NyaXB0IHRvIGdhdGhlciBmbGFnc3RhdHMKbCA8LSBsaXN0KCkKCmZvciAocyBpbiBTRVEpewogIAogIGxbW3NdXSA8LSByZWFkX3RhYmxlMihwYXN0ZSgiZGF0YS9TRVEvIiwgcywgIi9iYW1saXN0Lmxpc3QiLCBzZXAgPSIiKSwgY29sX25hbWVzID0gIkJBTSIpICU+JQogICAgbXV0YXRlKFBBVEggPSBwYXN0ZSgiZGF0YS9TRVEvIiwgcywgIi8iLCBzZXAgPSAiIiksCiAgICAgICAgICAgQ09NTUFORCA9ICJzYW10b29scyBmbGFnc3RhdCIsCiAgICAgICAgICAgT1VUID0gcGFzdGUoIj4+IGRhdGEvU0VRLyIsIHMsICIuZmxhZ3N0YXRzIiwgc2VwID0gIiIpKSAlPiUKICAgIHNlbGVjdCggQ09NTUFORCwgUEFUSCwgQkFNLCBPVVQpICU+JQogICAgdW5pdGUoRklMRSwgMjozLCBzZXAgPSAiIikKCn0KCmJhbSA8LSBsZHBseShsLCBkYXRhLmZyYW1lKSAlPiUKICBzZWxlY3QoLWAuaWRgKQoKd3JpdGVfZGVsaW0oYmFtLCAic2NyL2ZsYWdzdGF0cy5zaCIsIGRlbGltID0gIlx0IiwgY29sX25hbWVzID0gRkFMU0UpCgpgYGAKClJ1biBmbGFnc3RhdHMuCgpgYGB7YmFzaCBydW4gZmxhZ3N0YXRzLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKY2htb2QgNzU1IHNjci9mbGFnc3RhdHMuc2gKLi9zY3IvZmxhZ3N0YXRzLnNoCgpgYGAKCldyaXRlIHNjcmlwdCB0byBnYXRoZXIgaWR4c3RhdHMgZnJvbSBhbGwgYGJhbWAtZmlsZXMuCgpgYGB7ciBzY3JpcHQgaWR4c3RhdHN9CgojIHdyaXRlIHNjcmlwdCB0byBnYXRoZXIgaWR4c3RhdHMKbCA8LSBsaXN0KCkKCmxbWyJCTUExIl1dIDwtIHJlYWRfdGFibGUyKCJkYXRhL1NFUS9CTUEtMS9iYW1saXN0Lmxpc3QiLCBjb2xfbmFtZXMgPSAiQkFNIikgJT4lCiAgbXV0YXRlKFBBVEggPSAiZGF0YS9TRVEvQk1BLTEvIiwKICAgICAgICAgQ09NTUFORCA9ICJzYW10b29scyBpZHhzdGF0cyIsCiAgICAgICAgIE9VVCA9ICI+PiBkYXRhL1NFUS9CTUExLmlkeHN0YXRzIikgJT4lCiAgc2VsZWN0KCBDT01NQU5ELCBQQVRILCBCQU0sIE9VVCkgJT4lCiAgdW5pdGUoRklMRSwgMjozLCBzZXAgPSAiIikKCmxbWyJCTUEyIl1dIDwtIHJlYWRfdGFibGUyKCJkYXRhL1NFUS9CTUEtMi9iYW1saXN0Lmxpc3QiLCBjb2xfbmFtZXMgPSAiQkFNIikgJT4lCiAgbXV0YXRlKFBBVEggPSAiZGF0YS9TRVEvQk1BLTIvIiwKICAgICAgICAgQ09NTUFORCA9ICJzYW10b29scyBpZHhzdGF0cyIsCiAgICAgICAgIE9VVCA9ICI+PiBkYXRhL1NFUS9CTUEyLmlkeHN0YXRzIikgJT4lCiAgc2VsZWN0KCBDT01NQU5ELCBQQVRILCBCQU0sIE9VVCkgJT4lCiAgdW5pdGUoRklMRSwgMjozLCBzZXAgPSAiIikKCmxbWyJCTUEzIl1dIDwtIHJlYWRfdGFibGUyKCJkYXRhL1NFUS9CTUEtMy9iYW1saXN0Lmxpc3QiLCBjb2xfbmFtZXMgPSAiQkFNIikgJT4lCiAgbXV0YXRlKFBBVEggPSAiZGF0YS9TRVEvQk1BLTMvIiwKICAgICAgICAgQ09NTUFORCA9ICJzYW10b29scyBpZHhzdGF0cyIsCiAgICAgICAgIE9VVCA9ICI+PiBkYXRhL1NFUS9CTUEzLmlkeHN0YXRzIikgJT4lCiAgc2VsZWN0KCBDT01NQU5ELCBQQVRILCBCQU0sIE9VVCkgJT4lCiAgdW5pdGUoRklMRSwgMjozLCBzZXAgPSAiIikKCmJhbSA8LSBsZHBseShsLCBkYXRhLmZyYW1lKSAlPiUKICBzZWxlY3QoLWAuaWRgKQoKd3JpdGVfZGVsaW0oYmFtLCAic2NyL2lkeHN0YXRzLnNoIiwgZGVsaW0gPSAiXHQiLCBjb2xfbmFtZXMgPSBGQUxTRSkKCmBgYAoKUnVuIGluZHhzdGF0cy4KCmBgYHtiYXNoIHJ1biBpZHhzdGF0cywgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCmNobW9kIDc1NSBzY3IvaWR4c3RhdHMuc2gKLi9zY3IvaWR4c3RhdHMuc2gKCmBgYAoKIyMjIEZvcm1hdCBzdGF0cyBmaWxlcyBpbnRvIHRpZHkgZGF0YSBzZXRzCgpBcHBlbmRpbmcgdGhlIGZpbGUgcmVzdWx0cyBpbiB0aGUgaW5mb3JtYXRpb24gcGVyIGluZGl2aWR1YWwgYmVpbmcgcHJpbnRlZCBpbiBhIG5ldyBzZXQgb2Ygcm93IGJlaW5nIGFwcGVuZGVkIHRvIHRoZSBmaWxlLCBpLmUuIHRoZXJlIHdpbGwgYmUgYXMgbWFueSByb3dzIGZvciBhIGdpdmVuIGxvY3VzIGFzIGluZGl2aWR1YWxzIHdlcmUgbWFwcGVkLiBUaGUgZmlsZSBjYW4gYmUgcmUtZm9ybWF0dGVkIGFuZCBzdW1tYXJ5IHN0YXRpc3RpY3MgY2FsY3VsYXRlZCB1c2luZyBkcGx5ciBhbmQgdGlkeXIuCgpGb3JtYXQgaWR4c3RhdHM6CgpgYGB7ciBmb3JtYXQgaWR4c3RhdHN9CgojIGNyZWF0ZSB2ZWN0b3JzIG9mIGZpbGVzIHRvIGJlIGltcG9ydGVkLCByZWZlcmVuY2UgY29kZXMsIEsxIGFuZCBLMiwgZGF0YWZyYW1lIG5hbWVzCmZpbGVuYW1lcyA8LSBsaXN0LmZpbGVzKHBhdGggPSAiZGF0YS9TRVEiLCBwYXR0ZXJuID0gIiouaWR4c3RhdHMiKQpuYW1lcyA8LSBzdWJzdHIoZmlsZW5hbWVzLCAxLCA4KQpsaWIgPC0gc3Vic3RyKGZpbGVuYW1lcywgMSwgNCkKCiMgaW1wb3J0IGRhdGEKZm9yIChpIGluIG5hbWVzKXsKICBmaWxlcGF0aCA8LSBmaWxlLnBhdGgoImRhdGEvU0VRIiwgcGFzdGUoaSwgJ3N0YXRzJywgc2VwID0iIikpCiAgYXNzaWduKGksIHJlYWQudGFibGUoZmlsZXBhdGgsIHNlcCA9ICIiLCBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygiTG9jdXMiLCAiTGVuZ3RoIiwgIlJlYWRzX01hcHBlZCIsICdibGFuaycpKSAlPiUKICAgICAgICAgICBzZWxlY3QoMTozKSkKICB9CgojICMgbWFrZSBzdXJlIHRvIGRlbGV0ZSBvbGQgbGlzdCBpZiByZXJ1bm5pbmcgdGhlIGNvZGUKcm0oZGZsaXN0X2lkeCkKcm0oTWFwU3RhdHMuaWR4KQoKIyBDcmVhdGUgbGlzdCBvZiBvbmUgZGF0YWZyYW1lIHBlciBpZHhzdGF0cyBmaWxlIGFuZCBncm91cCBieSBsb2N1cwpkZmxpc3RfaWR4IDwtIGxhcHBseShscyhwYXR0ZXJuID0gIiouaWR4IiksIGdldCkKCmZvciAoZGYgaW4gMTpsZW5ndGgoZGZsaXN0X2lkeCkpewogIHggPC0gZGZsaXN0X2lkeFtbZGZdXQogIHhbWydMb2N1cyddXSA8LSBhcy5jaGFyYWN0ZXIoeFtbJ0xvY3VzJ11dKQogIHggPSB4ICU+JSBncm91cF9ieShMb2N1cykKICBkZmxpc3RfaWR4W1tkZl1dIDwtIHgKfQoKIyBDcmVhdGUgbmV3IGRhdGFmcmFtZXMgd2l0aCBzdW1tYXJ5IHN0YXRzIHBlciBsaWJyYXJ5IGFuZCBiaW5kIGludG8gZmluYWwgb3V0cHV0L2RhdGFmcmFtZQpNYXBTdGF0cy5pZHggPC0gZGF0YS5mcmFtZSgpCgpmb3IgKGRmIGluIDE6bGVuZ3RoKGRmbGlzdF9pZHgpKXsKICAgIAogIHggPSBzdW1tYXJpemUoZGZsaXN0X2lkeFtbZGZdXSwKICAgICAgICAgICAgICAgIExlbmd0aCA9IG1lYW4oTGVuZ3RoKSwKICAgICAgICAgICAgICAgIE1lYW5fTWFwcGVkID0gbWVhbihSZWFkc19NYXBwZWQpLAogICAgICAgICAgICAgICAgU3VtX01hcHBlZCA9IHN1bShSZWFkc19NYXBwZWQpLAogICAgICAgICAgICAgICAgTWluX01hcHBlZCA9IG1pbihSZWFkc19NYXBwZWQpLAogICAgICAgICAgICAgICAgTWF4X01hcHBlZCA9IG1heChSZWFkc19NYXBwZWQpLAogICAgICAgICAgICAgICAgU0RfTWFwcGVkID0gc2QoUmVhZHNfTWFwcGVkKSkKICB4W3ggPT0gMF0gPC0gTkEKCiAgdGVtcCA8LSBzdW1tYXJpemUoeCwgTWVhbl9NYXBwZWRfTm9uMCA9IG1lYW4oTWVhbl9NYXBwZWQsIG5hLnJtID0gVFJVRSkpICU+JQogICAgbXV0YXRlKExpYiA9IGxpYltkZl0sCiAgICAgICAgICAgTm90X01hcHBlZCA9IG5yb3coZmlsdGVyKHgsIGlzLm5hKFN1bV9NYXBwZWQpKSksCiAgICAgICAgICAgTl9Mb2NpX1JlZiA9IG5yb3coeCkpICU+JQogICAgc2VsZWN0KExpYiwgTl9Mb2NpX1JlZiwgTm90X01hcHBlZCwgTWVhbl9NYXBwZWRfTm9uMCkKCiAgTWFwU3RhdHMuaWR4IDwtIGJpbmRfcm93cyhNYXBTdGF0cy5pZHgsIHRlbXApCn0KCk1hcFN0YXRzLmlkeCA8LSBNYXBTdGF0cy5pZHggJT4lCiAgbXV0YXRlKFBST1BfRU1QVFkgPSByb3VuZCgoTm90X01hcHBlZC9OX0xvY2lfUmVmKSoxMDAsIGRpZ2l0cyA9IDIpLAogICAgICAgICBDT05USUdTX01BUFBFRCA9IE5fTG9jaV9SZWYgLSBOb3RfTWFwcGVkKQoKd3JpdGUudGFibGUoTWFwU3RhdHMuaWR4LCAicmVzdWx0cy9NYXBTdGF0cy5pZHgiLCBxdW90ZSA9IEZBTFNFKQoKIyByZW1vdmUgbGFyZ2UgKGR1cGxpY2F0ZSkgZmlsZXMKcm0oQk1BMS5pZHgpCnJtKEJNQTIuaWR4KQpybShCTUEzLmlkeCkKCk1hcFN0YXRzLmlkeAoKYGBgCgpGb3JtYXQgZmxhZ3N0YXRzOgoKYGBge3IgZm9ybWF0IGZsYWdzdGF0c30KCiMgRmlsZXMgdG8gYmUgaW1wb3J0ZWQKZmlsZW5hbWVzIDwtIGxpc3QuZmlsZXMocGF0aD0nZGF0YS9TRVEnLCBwYXR0ZXJuID0gJyouZmxhZ3N0YXRzJykKCiMgY3JlYXRlIHZlY3RvcnMgb2YgZmlsZXMgdG8gYmUgaW1wb3J0ZWQKbmFtZXMgPC0gc3Vic3RyKGZpbGVuYW1lcywgMSwgOSkKbGliIDwtIHN1YnN0cihmaWxlbmFtZXMsIDEsIDQpCgojIGltcG9ydCBkYXRhCmZvciAoaSBpbiBuYW1lcyl7CiAgZmlsZXBhdGggPC0gZmlsZS5wYXRoKCdkYXRhL1NFUScsIHBhc3RlKGksICdzdGF0cycsIHNlcCA9IiIpKQogIGFzc2lnbihpLCByZWFkLmNzdihmaWxlcGF0aCwgc2VwID0gIisiLCBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygiTl9SZWFkcyIsICJDQVQiKSwKICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICAgICAgICAgICBzZWxlY3QoMToyKSkKfQoKIyBDcmVhdGUgbGlzdCBvZiBvbmUgZGF0YWZyYW1lIHBlciBmbGFnc3RhdHMgZmlsZSBhbmQgY3JlYXRlIHRpZHkgZGF0YSBzZXQKIyBzaG91bGQgYmUgMyBlbGVtZW50cy9saWJyYXJpZXMKcm0oZGZsaXN0X2ZsYWcpCgpkZmxpc3RfZmxhZyA8LSBsYXBwbHkobHMocGF0dGVybiA9ICIqZmxhZyIpLCBnZXQpCgojIENoYW5nZSBOX1JlYWRzIHRvIG51bWVyaWMKZm9yIChkZiBpbiAxOmxlbmd0aChkZmxpc3RfZmxhZykpewogIHggPC0gZGZsaXN0X2ZsYWdbW2RmXV0KICB4W1snTl9SZWFkcyddXSA8LSBhcy5udW1lcmljKHhbWydOX1JlYWRzJ11dKQogIGRmbGlzdF9mbGFnW1tkZl1dIDwtIHgKfQoKZm9yIChkZiBpbiAxOmxlbmd0aChkZmxpc3RfZmxhZykpewogIHggPC0gZGZsaXN0X2ZsYWdbW2RmXV0KICAKICBuIDwtIG5yb3coeCkvMTQKCiAgeCA8LSB4ICU+JQogICAgZmlsdGVyKGdyZXBsKCIwIG1hcHBlZHxwcm9wZXJseSBwYWlyZWR8bWFwUT49NSIsIENBVCkpICU+JQogICAgbXV0YXRlKE1BUFNUQVQgPSBpZmVsc2UoZ3JlcGwoIm1hcFE+PTUiLCBDQVQpLCAiTWlzbWF0Y2giLAogICAgICAgICAgICAgICAgICAgaWZlbHNlKGdyZXBsKCJwcm9wZXJseSIsIENBVCksICJQcm9wX1BhaXJlZCIsICJNYXBwZWQiKSkpICU+JQogICAgbXV0YXRlKEluZCA9IGMocmVwKDE6biwgZWFjaCA9IDMpKSkgJT4lIAogICAgIyBub3Qgc3VyZSBpZiBleHRyYSBpbmRpdmlkdWFsIGluIHRoZXJlIHNvbWVob3cKICAgIHNlbGVjdCg0LCAzLCAxKSAlPiUKICAgIHNwcmVhZChNQVBTVEFULCBOX1JlYWRzKQoKICBkZmxpc3RfZmxhZ1tbZGZdXSA8LSB4Cn0KCiMgQ3JlYXRlIG5ldyBkYXRhZnJhbWVzIHdpdGggc3VtbWFyeSBzdGF0cyBhbmQgYWRkIHRvIG1haW4gZmluYWwgZGF0YSBmcmFtZQpNYXBTdGF0cy5mbGFnIDwtIGRhdGEuZnJhbWUoKQoKZm9yIChkZiBpbiAxOmxlbmd0aChkZmxpc3RfZmxhZykpewogIHggPSBzdW1tYXJpemUoZGZsaXN0X2ZsYWdbW2RmXV0sIFN1bV9NYXBwZWQgPSBzdW0oTWFwcGVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWFkc19NYXBwZWQgPSBtZWFuKE1hcHBlZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3VtX1BhaXJlZCA9IHN1bShQcm9wX1BhaXJlZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWVhbl9QYWlyZWQgPSBtZWFuKFByb3BfUGFpcmVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdW1fTWlzbWF0Y2ggPSBzdW0oTWlzbWF0Y2gpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1lYW5fTWlzbWF0Y2ggPSBtZWFuKE1pc21hdGNoKSkgJT4lCiAgbXV0YXRlKExpYiA9IGxpYltkZl0pICU+JQogIHNlbGVjdCg3LCAxOjYpCiAgTWFwU3RhdHMuZmxhZyA8LSBiaW5kX3Jvd3MoTWFwU3RhdHMuZmxhZywgeCkKfQoKIyB3cml0ZSB0byBmaWxlCndyaXRlLnRhYmxlKE1hcFN0YXRzLmZsYWcsICJyZXN1bHRzL01hcFN0YXRzLmZsYWciLCBxdW90ZSA9IEZBTFNFKQoKTWFwU3RhdHMuZmxhZwoKIyBjb21iaW5lIGZpbGVzCm1hcHN0YXRzIDwtIGxlZnRfam9pbihNYXBTdGF0cy5pZHgsIE1hcFN0YXRzLmZsYWcpICU+JQogIG11dGF0ZShQUk9QX01JU01BVENIID0gU3VtX01pc21hdGNoL1N1bV9NYXBwZWQpCgojIHdyaXRlIHN1bW1hcnkgc3RhdHMgZmlsZQp3cml0ZS50YWJsZShtYXBzdGF0cywgZmlsZSA9ICJyZXN1bHRzL0JXQV9tYXBwaW5nLnN0YXRzIiwgcXVvdGUgPSBGQUxTRSwgc2VwID0gIiAiKQoKYGBgCgojIyMgRXZhbHVhdGUgJiBjb21wYXJlIG1hcHBpbmcgcmVzdWx0cwoKQ29tcGFyZSBudW1iZXIgb2YgcmVmZXJlbmNlIGNvbnRpZ3MgZm9yIHdoaWNoIG5vIHJlYWRzIG1hcHBlZCB0byBwZXIgbGlicmFyeS4KCmBgYHtyIHBsb3QgbWFwc3RhdHMsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKbWFwc3RhdHMgPC0gcmVhZF9kZWxpbSgicmVzdWx0cy9CV0FfbWFwcGluZy5zdGF0cyIsIGRlbGltID0gIiAiKQoKIyBwbG90IG5vIG9mIGxvY2kgdnMgImVtcHR5IiBsb2NpCnAxIDwtIGdncGxvdChtYXBzdGF0cywgYWVzKHggPSBMaWIsIHkgPSBDT05USUdTX01BUFBFRCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMC4wNSkpICsKICBsYWJzKHggPSAibGlicmFyeSIsIHkgPSAiJSBjb250aWdzIHcvbm8gcmVhZHMgbWFwcGVkIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMiA8LSBnZ3Bsb3QobWFwc3RhdHMsIGFlcyh4ID0gTGliLCB5ID0gUmVhZHNfTWFwcGVkKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBsYWJzKHggPSAibGlicmFyeSIsIHkgPSAibWVhbiByZWFkcyBtYXBwZWQgcGVyIGluZHYiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAzIDwtIGdncGxvdChtYXBzdGF0cywgYWVzKHggPSBMaWIsIHkgPSBQUk9QX01JU01BVENIKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBsYWJzKHggPSAiIix5ID0gIiUgcmVhZHMgbm90IG1hcHBlZCBhcyBwYWlyIikgKwogIHRoZW1lX3N0YW5kYXJkCgptdWx0aXBsb3QocDEsIHAyLCBwMywgY29scyA9IDMpCgpgYGAKCiMgU05QIGNhbGxpbmcKClRyYW5zZmVyIGNvcHkgb2YgYHJlZmVyZW5jZS5mYXN0YWAgYW5kIGFzc29jaWF0ZWQgZmlsZXMgaW50byBTTlAgY2FsbGluZyBkaXJlY3RvcnkuCgpDcmVhdGUgc3ltbGlua3MgZnJvbSBhbGwgYGZxYCwgYGJhbWAgYW5kIGBiYW0uYmFpYC1maWxlcyBmb3IgZWFjaCBzZXBhcmF0ZWx5IG1hcHBlZCBsaWJyYXJ5IGluIGBTTlBfQ2FsbGluZ2AgZm9sZGVyLgoKYGBge2Jhc2ggc29mdGxpbmsgZmlsZXMsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpsbiAtcyAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU0VRL0JNQS0xLyouZnEuZ3ogL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9kYXRhL1NOUF9DYWxsaW5nCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvZGF0YS9TRVEvQk1BLTEvKi5iYW0qIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvZGF0YS9TTlBfQ2FsbGluZwoKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9kYXRhL1NFUS9CTUEtMi8qLmZxLmd6IC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvZGF0YS9TTlBfQ2FsbGluZwpsbiAtcyAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU0VRL0JNQS0yLyouYmFtKiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvZGF0YS9TRVEvQk1BLTMvKi5mcS5neiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9kYXRhL1NFUS9CTUEtMy8qLmJhbSogL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9kYXRhL1NOUF9DYWxsaW5nCgojIHJlbW92ZSB1bm5lY2Vzc2FyeSBmaWxlcwpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKcm0gY2F0LVJSRy5iYW0qCgpgYGAKCkV4ZWN1dGUgYGREb2NlbnRgIGZyb20gd2l0aGluIGBTTlBfQ2FsbGluZ2AtZm9sZGVyIHRvIGNhbGwgdmFyaWFudHMgYWNyb3NzIGFsbCBpbmRpdmlkdWFscyAoYWxsIGxpYnJhcmllcykuCgpgYGB7YmFzaCBjYWxsIFNOUHMsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKZERvY2VudAoKYGBgCgpGaWxlIGBUb3RhbHJhd1NOUHMudmNmYCBjb250YWlucyBhbGwgcmF3IFNOUC9JTkRFTCBjYWxscy4gRG8gbm90IG5lZWQgdG8ga2VlcCBsaW5rcyBvZiBgZnEuZ3pgLSwgYGJhbWAtLCBgLmJhbS5iYWlgLWZpbGVzIGFmdGVyIFNOUHMgaGF2ZSBiZWVuIGNhbGxlZC4gQ29weSBgVG90YWxSYVNOUHMudmNmYCB0byBgVkNGYCBmb3IgU05QIGZpbHRlcmluZy4KCmBgYHtiYXNoIGNvcHkgVG90YWxSYXdTTlBzIGZvciBmaWx0ZXJpbmcsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcKcm0gKmZxLmd6ICpiYW0qCgpjcCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvU05QX0NhbGxpbmcvVG90YWxSYXdTTlBzLnZjZiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL2RhdGEvVkNGL3RlbXAvCgpgYGAKCiMgU05QIGZpbHRlcmluZwoKYGREb2NlbnRgIHVzZXMgYEZyZWVCYXllc2AgdG8gY2FsbCBTTlBzIGFuZCB3cml0ZSBhIFZDRi1maWxlIGBUb3RhbHJhd1NOUHMudmNmYC4gVGhpcyBkYXRhIHNldCB3YXMgZmlsdGVyZWQgdG8gcmVtb3ZlIGxvdyBxdWFsaXR5IGFuZCBhcnRlZmFjdHVhbCBTTlAgc2l0ZXMsIHBhcmFsb2dzIGFuZCBsb3cgcXVhbGl0eSBpbmRpdmlkdWFscyBiYXNlZCBvbiBsZXZlbHMgb2YgbWlzc2luZyBkYXRhLCBtaW5pbXVtL21heGltdW0gcmVhZCBkZXB0aCwgZ2Vub3R5cGUgY2FsbCByYXRlLCBhbmQgbWlub3IgYWxsZWxlIGZyZXF1ZW5jaWVzLiBDb250aWdzIG1heSBjb250YWluIG1vcmUgdGhhbiBvbmUgU05QOyB0aGUgc2NyaXB0IGByYWRfaGFwbG90eXBlci5wbGAgd2FzIHVzZWQgdG8gY3JlYXRlIGhhcGxvdHlwZXMgZm9yIGVhY2ggbG9jdXMuCgojIyBSYXcgZGF0YSAKCiMjIyBJbmRpdmlkdWFscy9Qb3B1bGF0aW9ucyBzYW1wbGVkCgpHZW5lcmF0ZSBhIGxpc3Qgb2YgYWxsIGluZGl2aWR1YWxzIGluY2x1ZGVkIGluIHRoZSBTTlAgZGF0YSBzZXQgY2FsbGVkIGJ5IEZyZWVCYXllcyBpbiB0aGUgZERvY2VudCBwaXBlbGluZS4KCmBgYHtiYXNoIHdyaXRlIHJhdyBpbmR2fQoKdmNmc2FtcGxlbmFtZXMgZGF0YS9WQ0YvdGVtcC9Ub3RhbFJhd1NOUHMudmNmID4gZGF0YS9WQ0YvcmF3LmluZAoKYGBgCgpVc2UgYEluZF9yYXdgIGZpbGUgdG8gd3JpdGUgdGV4dCBmaWxlcyBvZiBpbmRpdmlkdWFscyBpbiBlYWNoIGxpYnJhcnkgYW5kIGluIHJlZ2lvbmFsIGdyb3VwaW5ncy4gCgpgYGB7ciBjcmVhdGUgSW5kIGZpbGVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBpbXBvcnQgaW5kaXZpZHVhbHMgaW4gcmF3IGRhdGEgc2V0IC0tLS0KSW5kX1JBVyA8LSByZWFkX2RlbGltKCJkYXRhL1ZDRi9yYXcuaW5kIiwgZGVsaW0gPSAiXHQiLCBjb2xfbmFtZXMgPSAiTElCX0lEIikgJT4lCiAgc2VwYXJhdGUoTElCX0lELCBpbnRvID0gYygiU1AiLCAiV0VMTCIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSwgZXh0cmEgPSAibWVyZ2UiKQoKIyBjcmVhdGUgZmlsZXMgd2l0aCBpbmRpdmlkdWFscyBieSBwb3B1bGF0aW9uIC0tLS0KClNhbXBsZUluZm8gPC0gcmVhZF9kZWxpbSgiZGF0YS9QT1BHRU4vU2FtcGxlSW5mby50eHQiLCBkZWxpbSA9ICJcdCIpCgpJbmRfUkFXIDwtIGxlZnRfam9pbihJbmRfUkFXLCBTYW1wbGVJbmZvKQoKcG9wcyA8LSB1bmlxdWUoSW5kX1JBVyRQT1ApCgpmb3IgKHAgaW4gcG9wcyl7CiAgCiAgZGYgPC0gSW5kX1JBVyAlPiUKICAgIGZpbHRlcihQT1AgPT0gcCkgJT4lCiAgICBzZWxlY3QoTElCX0lEKQogIAogIHdyaXRlX2RlbGltKGRmLCBwYXN0ZSgiZGF0YS9WQ0YvIiwgcCwgIi5pbmQiLCBzZXAgPSAiIiksCiAgICAgICAgICAgIGRlbGltID0gIiIsIGNvbF9uYW1lcyA9IEZBTFNFKQogIAp9CgoKIyBjcmVhdGUgZmlsZXMgd2l0aCBpbmRpdmlkdWFscyBwZXIgbGlicmFyeSAtLS0tCnRlbXAgPC0gSW5kX1JBVyAlPiUKICBmaWx0ZXIoZ3JlcGwoIjFBIiwgV0VMTCkgfAogICAgICAgICBncmVwbCgiMUIiLCBXRUxMKSkgJT4lCiAgc2VsZWN0KExJQl9JRCkKCndyaXRlLnRhYmxlKHRlbXAsICJkYXRhL1ZDRi9CTUExLmluZCIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCnRlbXAgPC0gSW5kX1JBVyAlPiUKICBmaWx0ZXIoZ3JlcGwoIjJBIiwgV0VMTCkgfAogICAgICAgICBncmVwbCgiMkIiLCBXRUxMKSkgJT4lCiAgc2VsZWN0KExJQl9JRCkKCndyaXRlLnRhYmxlKHRlbXAsICJkYXRhL1ZDRi9CTUEyLmluZCIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCnRlbXAgPC0gSW5kX1JBVyAlPiUKICBmaWx0ZXIoZ3JlcGwoIjNBIiwgV0VMTCkgfAogICAgICAgICBncmVwbCgiM0IiLCBXRUxMKSkgJT4lCiAgc2VsZWN0KExJQl9JRCkKCndyaXRlLnRhYmxlKHRlbXAsICJkYXRhL1ZDRi9CTUEzLmluZCIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCmBgYAoKIyMjIENvbXBhcmUgSW5kaXZpZHVhbCAmIFNOUCBzdGF0cwoKVXNlIGBWQ0Z0b29sc2AgdG8gY3JlYXRlIHN0YXRzIGZpbGVzIGZvciBkZXB0aCwgbWlzc2luZyBkYXRhLCBoZXRlcm96eWdvc2l0eSBhbmQgc2l0ZSBxdWFsaXR5IGZvciB0aGUgcmF3IGRhdGEuCgpgYGB7YmFzaCBxdWVyeSByYXcgc3RhdHN9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL1RvdGFsUmF3U05Qcy52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BX3JhdyAtLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tc2l0ZS1tZWFuLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tc2l0ZS1xdWFsaXR5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tbWlzc2luZy1pbmR2CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tbWlzc2luZy1zaXRlCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0taGV0CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUFfcmF3IC0tc2luZ2xldG9ucwoKYGBgCgpDb21wYXJlIHJhdyBzdGF0cy4KICAgIApgYGB7ciBzdGF0cyByYXcsIGZpZy5oZWlnaHQ9MjAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19yYXcgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQV9yYXciKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiU1AiLCAiTElCIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFKQoKbG9jX3N0YXRzX3JhdyA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQV9yYXciKQoKIyBwbG90IG1pc3NpbmcgZGF0YSBwZXIgaW5kdiAtLS0tCnAxIDwtIGdncGxvdChpbmRfc3RhdHNfcmF3LCBhZXMoeCA9IE1JU1NfQk1BX3JhdykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWlzc2luZyBkYXRhIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgcmVhZCBkZXB0aCBwZXIgaW5kdiAtLS0tCnAyIDwtIGdncGxvdChpbmRfc3RhdHNfcmF3LCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BX3JhdykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRIX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gcmVhZCBkZXB0aCBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IGRlcHRoIHZzIG1pc3NpbmcgLS0tLQpwMyA8LSBnZ3Bsb3QoaW5kX3N0YXRzX3JhdywgYWVzKHggPSBNRUFOX0RFUFRIX0JNQV9yYXcsIHkgPSBNSVNTX0JNQV9yYXcpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRIX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4oTUlTU19CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBGaXMgcGVyIGluZHYgLS0tLQpwNCA8LSBnZ3Bsb3QoaW5kX3N0YXRzX3JhdywgYWVzKHggPSBGaXNfQk1BX3JhdykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiRmlzIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgRmlzIHZzIG1pc3NpbmcgZGF0YSBwZXIgaW5kdiAtLS0tCnA1IDwtIGdncGxvdChpbmRfc3RhdHNfcmF3LCBhZXMoeCA9IEZpc19CTUFfcmF3LCB5ID0gTUlTU19CTUFfcmF3KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDAuNSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJGaXMgcGVyIGluZHYiLCB5ID0gIiUgbWlzc2luZyBkYXRhIikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgRmlzIHZzIG1lYW4gZGVwdGggcGVyIGluZHYgLS0tLQpwNiA8LSBnZ3Bsb3QoaW5kX3N0YXRzX3JhdywgYWVzKHggPSBGaXNfQk1BX3JhdywgeSA9IE1FQU5fREVQVEhfQk1BX3JhdykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKEZpc19CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJGaXMgcGVyIGluZHYiLCB5ID0gIm1lYW4gZGVwdGggcGVyIGluZHYiKSArCiAgdGhlbWVfc3RhbmRhcmQKCgojIHBsb3QgZGlzdHJpYnV0aW9uIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMgLS0tLQpwNyA8LSBnZ3Bsb3QobG9jX3N0YXRzX3JhdywgYWVzKHggPSBNSVNTX0JNQV9yYXcpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQV9yYXcsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDAuMSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIlIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWVhbiByZWFkIGRlcHRoIC0tLS0KcDggPC0gZ2dwbG90KGxvY19zdGF0c19yYXcsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUFfcmF3KSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMjAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BX3JhdywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggdnMgbWlzc2luZyBkYXRhIC0tLS0KcDkgPC0gZ2dwbG90KGxvY19zdGF0c19yYXcsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUFfcmF3LCB5ID0gTUlTU19CTUFfcmF3KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUFfcmF3LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BX3JhdywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMC4xKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gZGVwdGggcGVyIGxvY3VzIiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IGRlcHRoIHZzIFNOUCBxdWFsaXR5IC0tLS0Kc2l0ZV9xdWFsIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQV9yYXcubHF1YWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBtdXRhdGUoUFJPQiA9IDEwXigtUVVBTC8xMCkpCgp0ZW1wIDwtIGRhdGEuZnJhbWUobG9jX3N0YXRzX3JhdyRNRUFOX0RFUFRIX0JNQV9yYXcsIHNpdGVfcXVhbCRRVUFMKSAlPiUKICByZW5hbWUoZGVwdGggPSBsb2Nfc3RhdHNfcmF3Lk1FQU5fREVQVEhfQk1BX3JhdywgcXVhbCA9IHNpdGVfcXVhbC5RVUFMKQoKcDEwIDwtIGdncGxvdCh0ZW1wLCBhZXMoeCA9IGRlcHRoLCB5ID0gcXVhbCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oZGVwdGgsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4ocXVhbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgbG9jdXMiLCB5ID0gIlNOUCBxdWFsaXR5IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgbnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyB2cy4gbWVhbiBkZXB0aCAtLS0tCnRlbXAgPC0gbG9jX3N0YXRzX3JhdyAlPiUKICBjb3VudChDSFIpCgpwMTEgPC0gbGVmdF9qb2luKHRlbXAsIGxvY19zdGF0c19yYXcpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gbiwgeSA9IE1FQU5fREVQVEhfQk1BX3JhdykpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyIsIHkgPSAibWVhbiBkZXB0aCIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IG5vIG9mIFNOUHMgcGVyIGxvY3VzIC0tLS0KcDEyIDwtIGxvY19zdGF0c19yYXcgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGxhYnMoeCA9ICJudW1iZXIgb2YgU05QcyBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCm1yYXcgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgcDExLCBwMTIsIGNvbHM9MikKCmBgYAoKIyMgQ2hvb3NlIHRocmVzaG9sZCB2YWx1ZXMgZm9yIHF1YWxpdHkgc2NvcmUsIGNvdmVyYWdlLCBtaXNzaW5nIGRhdGEsIG1pbm9yIGFsbGVsZXMgYW5kIG1hcHBpbmcvdmFyaWFudCBjYWxsaW5nIGFydGlmYWN0cwoKIyMjIEZpbHRlciAwOiBSZW1vdmUgTFEgaW5kaXZpZHVhbHMKClJlbW92ZSAoa25vd24pIGxvdyBxdWFsaXR5IGluZGl2aWR1YWxzIGZyb20gZGF0YSBzZXQ6CgpJZGVudGlmeSBsb3cgcXVhbGl0eSBpbmRpdmlkdWFscyB0byByZW1vdmUgZnJvbSB0aGUgZGF0YSBzZXQ7IGRlZmluZWQgYXMgaW5kaXZpZHVhbHMgd2l0aCBhIG1lYW4gY292ZXJhZ2Ugb2YgZml2ZSBvciBsZXNzIHJlYWRzIGFjcm9zcyBhbGwgbG9jaSwgd2l0aCBtb3JlIHRoYW4gMzElIG1pc3NpbmcgZGF0YSwgb3IgRmlzID4gKHRocmVzaG9sZHMgYmFzZWQgb24gZXhwbG9yYXRvcnkgZmlsdGVyaW5nKS4KCgpgYGB7ciBscSBpbmR2fQoKTFFpbmR2IDwtIGluZF9zdGF0c19yYXcgJT4lCiAgZmlsdGVyKE1FQU5fREVQVEhfQk1BX3JhdyA8PSA1IHwgTUlTU19CTUFfcmF3ID49IDAuMzEgfCBGaXNfQk1BX3JhdyA+IDAuMikgJT4lCiAgc2VsZWN0KElORFYpCgp3cml0ZV9kZWxpbShMUWluZHYsICJkYXRhL1ZDRi9MUV9yYXcuaW5kIiwgZGVsaW0gPSAiXHQiKQoKbnJvdyhMUWluZHYpCgpgYGAKClJlbW92ZSBsb3cgcXVhbGl0eSBpbmRpdmlkdWFscyBhbmQgZGVjb21wb3NlIGluZGVscy4KCmBgYHtiYXNoIGZpbHRlciBscSBpbmR2LCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKIyBkZWNvbXBvc2UgaW5kZWxzCnZjZmFsbGVsaWNwcmltaXRpdmVzIGRhdGEvVkNGL3RlbXAvVG90YWxSYXdTTlBzLnZjZiAtLWtlZXAtaW5mbyAtLWtlZXAtZ2VubyA+IGRhdGEvVkNGL3RlbXAvQk1BLnByaW0udmNmCgojIHJldGFpbiBvbmx5IFNOUHMgLyByZW1vdmUgTFEgaW5kaXZpZHVhbHMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEucHJpbS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEuRjAgLS1yZW1vdmUtaW5kZWxzIC0tcmVtb3ZlIGRhdGEvVkNGL0xRX3Jhdy5pbmQgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCiMgcXVlcnkgc3RhdHMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjAucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjAgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLXNpdGUtbWVhbi1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLW1pc3NpbmctaW5kdgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLWhldAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMCAtLXNpbmdsZXRvbnMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjAucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjAgLS1nZW5vLWRlcHRoCgpgYGAKCkNvbXBhcmUgc3RhdHM6CgpgYGB7ciBzdGF0cyBGMCwgZmlnLmhlaWdodD0yMCwgZmlnLndpZHRoPTEwLCBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9VFJVRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GMCA8LSByZWFkLmluZC5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YiLCB2Y2YgPSAiQk1BLkYwIikgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlNQIiwgIkxJQiIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSwgZXh0cmEgPSAibWVyZ2UiKQoKbG9jX3N0YXRzX0YwIDwtIHJlYWQubG9jLnN0YXRzKGRpciA9ICJkYXRhL1ZDRi8iLCB2Y2YgPSAiQk1BLkYwIikKCmBgYAoKRGF0YSBzZXQgY29udGFpbnMgYHIgbnJvdyhpbmRfc3RhdHNfRjApYCBpbmRpdmlkdWFscyBhbmQgYHIgbnJvdyhsb2Nfc3RhdHNfRjApYCBsb2NpIGFmdGVyIHJlbW92aW5nIGxvdyBxdWFsaXR5IGluZGl2aWR1YWxzIGFuZCBkZWNvbXBvc2luZyBpbmRlbHMgc2V0IGludG8gU05Qcy4KCkltcG9ydCBzaW5nbGV0b25zIGFuZCBnZW5vdHlwZSBkZXB0aCBmaWxlIHRvIGNyZWF0ZSBsaXN0IG9mIGxvY2kgdG8gZXhjbHVkZSBiYXNlZCBvbiBkZXB0aC4KCmBgYHtyIHJlYWQgc2luZ2xldG9uIGdlbm90eXBlIGRlcHRoLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBudW1iZXIgb2YgaW5kaXZpZHVhbHMKbiA8LSBucm93KGluZF9zdGF0c19GMCkrMgoKIyByZWFkIHNpbmdsZXRvbnMgZmlsZQpzaW5nbGV0b25zIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjAuc2luZ2xldG9ucyIpICU+JQogIG11dGF0ZShWQVJJQU5UID0gaWZlbHNlKEFMTEVMRSAlaW4lIGMoIkEiLCAiVCIsICJDIiwgIkciKSwgIlNOUCIsICJJTkRFTCIpKQoKY2hyb20gPC0gdW5pcXVlKHNpbmdsZXRvbnMkQ0hST00pCgojIHJlYWQgZ2Vub3R5cGUgZGVwdGggZmlsZSBhbmQgam9pbiB3aXRoIHNpbmdsZXRvbnMKZ2RlcHRoIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjAuZ2RlcHRoIikgJT4lCiAgZmlsdGVyKENIUk9NICVpbiUgY2hyb20pICU+JQogIGdhdGhlcihrZXkgPSBJTkRWLCB2YWx1ZSA9IERFUFRILCAzOm4pCgpzaW5nbGV0b25zIDwtIGxlZnRfam9pbihzaW5nbGV0b25zLCBnZGVwdGgpCiAgCmBgYAoKRGF0YSBzZXQgY29udGFpbnMgYG5yb3coc2luZ2xldG9ucylgIHNpbmdsZXRvbnMuCgpgYGB7ciBkb3VibGV0b25zfQoKIyBmaWx0ZXIgZG91YmxldG9ucwpkb3VibGV0b25zIDwtIHNpbmdsZXRvbnMgJT4lCiAgZmlsdGVyKGBTSU5HTEVUT04vRE9VQkxFVE9OYCA9PSAiRCIpCgpgYGAKCk9mIHRob3NlIGBucm93KGRvdWJsZXRvbnMpYCBhcmUgY2FsbGVkIGFzIGEgaG9tb3p5Z290ZSBpbiBvbmUgaW5kaXZpZHVhbC4KCmBgYHtyIHNpbmdsZXRvbnMgcGVyIGNvbnRpZywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NH0KCiMgbnVtYmVyIG9mIGNvbnRpZ3MgaW4gZGF0YSBzZXQKY29udGlnc190b3RhbCA8LSBsb2Nfc3RhdHNfRjAgJT4lCiAgZGlzdGluY3QoQ0hSKQoKY29udGlnc19zaW5nbGV0b25zIDwtIHNpbmdsZXRvbnMgJT4lCiAgZGlzdGluY3QoQ0hST00pCgpjb250aWdzIDwtIHNpbmdsZXRvbnMgJT4lCiAgY291bnQoQ0hST00pCgpnZ3Bsb3QoY29udGlncywgYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKG4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2Ygc2luZ2xldG9ucyBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKVGhlIGRhdGEgc2V0IGNvbnRhaW5zIGBucm93KGNvbnRpZ3NfdG90YWwpYCBjb250aWdzLCBgbnJvdyhjb250aWdzX3NpbmdsZXRvbnMpYCAoYDJyb3VuZCggKG5yb3coY29udGlnc19zaW5nbGV0b25zKS9ucm93KGNvbnRpZ3NfdG90YWwpKjEwMCksIGRpZ2l0cyA9IDIpYCUpIGNvbnRhaW4gc2luZ2xldG9ucy4KCmBgYHtyIGRpc3RyaWJ1dGlvbiBzaW5ncGxldG9ucyBwZXIgY29udGlnLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD02fQoKY29udGlncyA8LSBzaW5nbGV0b25zICU+JQogIGdyb3VwX2J5KGBTSU5HTEVUT04vRE9VQkxFVE9OYCkgJT4lCiAgY291bnQoQ0hST00pCgpnZ3Bsb3QoY29udGlncywgYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGZhY2V0X2dyaWQoLiB+IGBTSU5HTEVUT04vRE9VQkxFVE9OYCkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2YgZG91YmxldG9ucy9zaW5nZWx0b25zIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpUYXJnZXQgY292ZXJhZ2UgaXMgMjAgcmVhZHMgcGVyIGxvY3VzOyBmbGFnIHNpbmdsZXRvbnMgd2l0aCBkZXB0aCA8IDEwIHJlYWRzIGFuZCBkb3VibGV0b25zIHdpdGggZGVwdGggPCAyMCByZWFkcy4KCmBgYHtyfQoKc2luZ2xldG9ucyAlPiUgCiAgZ3JvdXBfYnkoYFNJTkdMRVRPTi9ET1VCTEVUT05gKSAlPiUKICBjb3VudChERVBUSCA8PSAxMCkKCmQgPC0gc2luZ2xldG9ucyAlPiUKICBmaWx0ZXIoYFNJTkdMRVRPTi9ET1VCTEVUT05gID09ICJEIiAmIERFUFRIIDw9IDIwKSAKICAKTFEgPC0gc2luZ2xldG9ucyAlPiUKICBmaWx0ZXIoREVQVEggPD0gMTApICU+JQogIGJpbmRfcm93cyhkKSAlPiUKICBzZWxlY3QoQ0hST00sIFBPUykKCndyaXRlX2RlbGltKExRLCAiZGF0YS9WQ0YvTFFfRjAubG9jaSIsIGRlbGltID0gIlx0IiwgY29sX25hbWVzID0gRkFMU0UpCgpgYGAKCkRpc3RyaXVidGlvbiBvZiBnZW5vdHlwZSBkZXB0aCBwZXIgc2luZ2xldG9uL2RvdWJsZXRvbi4KCmBgYHtyIGRpc3RyaWJ1dGlvbiBnZW5vIGRlcHRoIHBlciBzaW5nbGV0b24sIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTZ9CgpnZ3Bsb3Qoc2luZ2xldG9ucywgYWVzKHggPSBERVBUSCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBmYWNldF9ncmlkKC4gfiBgU0lOR0xFVE9OL0RPVUJMRVRPTmAsIHNjYWxlcyA9ICJmcmVlIikgKwogIGxhYnMoeCA9ICJyZWFkIGRlcHRoIikgKwogIHNjYWxlX3lfc3FydCgpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpRdWFudGlsZXMgZGlzdHJpYnV0aW9uIG9mIHJlYWQgZGVwdGggZm9yIFNOUCBsb2NpIGNhbGxlZCBpbiBvbmx5IG9uZSBpbmRpdmlkdWFsLgoKYGBge3IgcXVhbnRpbGUgc2luZ2xldG9uIGRlcHRofQoKcXVhbnRpbGUoc2luZ2xldG9ucyRERVBUSCwgcHJvYnMgPSBjKC4wNSwgLjI1LCAuNSwgLjc1LCAuOTUsIC45OSkpCgpgYGAKCkRpc3RyaWJ1dGlvbiBvZiBkb3VibGV0b25zIChob216eWdvdXMgZ2Vub3R5cGUgZm9yIHRoYXQgaW5kaXZpZHVhbCkgYW5kIHNpbmdsZXRvbnMgKGhldGVyb3p5Z290ZSBnZW5vdHlwZSkuCgpgYGB7ciBkaXN0cmlidXRpb24gbm8gc2luZ2xldG9ucyBwZXIgaW5kdiwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCkluZCA8LSBzaW5nbGV0b25zICU+JQogIGdyb3VwX2J5KGBTSU5HTEVUT04vRE9VQkxFVE9OYCkgJT4lCiAgY291bnQoSU5EVikKCkluZCA8LSBsZWZ0X2pvaW4oSW5kLCBpbmRfc3RhdHNfRjApCgpnZ3Bsb3QoSW5kLCBhZXMoeCA9IG4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1MCwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGZhY2V0X2dyaWQoLiB+IGBTSU5HTEVUT04vRE9VQkxFVE9OYCkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2Ygc2luZ2xldG9ucyBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpRdWFudGlsZXMgZGlzdHJpYnV0aW9uIG51bWJlciBvZiBzaW5nbGV0b25zIGNhbGxlZCBpbiBvbmUgaW5kaXZpZHVhbC4KCmBgYHtyIHF1YW50aWxlIHNpbmdsZXRvbnMgcGVyIGluZHZ9CgpxdWFudGlsZShJbmQkbiwgcHJvYnMgPSBjKC4wMSwgLjA1LCAuMjUsIC41LCAuNzUsIC45OSkpCgpgYGAKCkNvbXBhcmUgdGhlIG51bWJlciBvZiBTTlBzIHZzIGNvbXBsZXggdmFyaWFudHMgKElOREVMcykuCgpgYGB7ciBzaW5nbGV0b24gdmFyaWFudCB0eXBlfQoKY291bnQoc2luZ2xldG9ucywgVkFSSUFOVCkKCmBgYAoKIyMjIEZpbHRlciAxOiBDb25maWRlbmNlIGluIFNOUCBjYWxsCiAgICAKVGhlIFFVQUwgY29sdW1uIG9mIGEgVkNGIGZpbGUgaXMgYSBwaHJlZCBiYXNlZCBzY29yZSBpbmRpY2F0aW5nIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSB2YXJpYW50IHNob3duIGluIHRoZSBBTFQgY29sdW1uIGlzIHdyb25nLiBHaXZlbiB0aGUgUGhyZWQgcXVhbGl0eSBzY29yZSAoUSksIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIGJhc2UgaXMgaW5jb3JyZWN0bHkgY2FsbGVkIChQKSwgUSA9IC0xMChMb2cxMFApLiBBIHF1YWxpdHkgc2NvcmUgb2YgMjAgaW5kaWNhdGVzLCBhIDEgaW4gMTAwIGNoYW5jZSB0aGF0IHRoZSBTTlAgc2l0ZSBoYXMgYmVlbiBjYWxsZWQgaW5jb3JyZWN0bHkgKGkuZS4gOTklIHByb2JhYmlsaXR5IHRoYXQgY29ycmVjdCBjYWxsKS4KCkZpbHRlciBsb2NpIHdpdGggcXVhbGl0eSBzY29yZSA8IDIwIGFuZCBzaW5nbGV0b25zL2RvdWJsZXRvbnMgd2l0aCBsb3cgcmVhZCBkZXB0aCAoPDEwLzIwIHJlYWRzKS4gQ29kZSBnZW5vdHlwZXMgd2l0aCBnZW5vdHlwZSBjYWxsIHF1YWxpdHkgPCAyMCBvciAgZ2Vub3R5cGUgZGVwdGggPCA1IGFzIG1pc3NpbmcuCgpgYGB7YmFzaCBmaWx0ZXIgTFEgU05QIGNhbGxzfQoKIyBmaWx0ZXIgTFEgU05QIGNhbGxzCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYwLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEuRjEgLS1taW5RIDIwIC0tbWluR1EgMjAgLS1taW5EUCA1IC0tZXhjbHVkZS1wb3NpdGlvbnMgZGF0YS9WQ0YvTFFfRjAubG9jaSAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKIyBxdWVyeSBzdGF0cwp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMSAtLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tc2l0ZS1tZWFuLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tbWlzc2luZy1pbmR2CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tbWlzc2luZy1zaXRlCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0taGV0CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tZ2Vuby1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMSAtLXNpbmdsZXRvbnMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEgLS1pbmR2LWZyZXEtYnVyZGVuCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxIC0tZnJlcSAKCmBgYAoKQ29tcGFyZSBzdGF0cyBwb3N0LWZpbHRlcmluZy4KCmBgYHtyIHN0YXRzIEYxLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGxvYWQgc3RhdHMgZmlsZXMgLS0tLQppbmRfc3RhdHNfRjEgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5GMSIpICU+JQogIHNlcGFyYXRlKElORFYsIGludG8gPSBjKCJTUCIsICJMSUIiLCAiU0FNUExFX0lEIiksIHNlcCA9ICJfIiwgcmVtb3ZlID0gRkFMU0UpCgpsb2Nfc3RhdHNfRjEgPC0gcmVhZC5sb2Muc3RhdHMoZGlyID0gImRhdGEvVkNGLyIsIHZjZiA9ICJCTUEuRjEiKQoKYGBgCgpEYXRhIHNldCBjb250YWlucyBgciBucm93KGluZF9zdGF0c19GMSlgIGluZGl2aWR1YWxzIGFuZCBgciBucm93KGxvY19zdGF0c19GMSlgIFNOUCBzaXRlcy4KClJlbW92aW5nIGxvdyBjb25maWRlbmNlIFNOUCBsb2NpIGFuZCBnZW5vdHlwZSBjYWxscyByZXN1bHRzIGluIGEgcmVkdWN0aW9uIGluIHRoZSBudW1iZXIgb2YgdGhlIChtYXhpbXVtKSBTTlBzIHBlciBsb2N1cy4KCmBgYHtyIE4gU05QcywgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9NSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCnAxIDwtIGxvY19zdGF0c19yYXcgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKG4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCkpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIFNOUHMgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMiA8LSBsb2Nfc3RhdHNfRjEgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKG4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCkpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIFNOUHMgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgptMWEgPC0gbXVsdGlwbG90KHAxLCBwMiwgY29scz0xKQoKYGBgCgpDb2RpbmcgZ2Vub3R5cGVzIHdpdGggbG93IHJlYWQgZGVwdGggKDwgNSkgYXMgbWlzc2luZywgcmVzdWx0cyBpbiBhbiBvdmVyYWxsIGluY3JlYXNlIGluIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMgYW5kIGEgc2hpZnQgaW4gbW9yZSBpbmRpdmlkdWFscyB3aXRoIG1vcmUgbWlzc2luZyBkYXRhIC0gdGhpcyBpcyBiZWNhdXNlIGluZGl2aWR1YWxzIChhbmQgbG9jaSkgd2l0aCBjb3ZlcmFnZSBpc3N1ZXMgYXJlIG5vdyBjaGFyYWN0ZXJpemVkIGJ5IGhpZ2hlciBtaXNzaW5nIGRhdGEuCgpgYGB7ciBtaXNzaW5nIGRhdGEgRjEsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgppcmF3IDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQV9yYXcuaW1pc3MiLAogICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgc2VsZWN0KElORFYsIEZfTUlTUykgJT4lCiAgcmVuYW1lKHJhdyA9IEZfTUlTUykKCmltaXNzIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMS5pbWlzcyIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBzZWxlY3QoSU5EViwgRl9NSVNTKSAlPiUKICByZW5hbWUoRjEgPSBGX01JU1MpCgppbWlzcyA8LSBsZWZ0X2pvaW4oaW1pc3MsIGlyYXcpCgpwMSA8LSBnZ3Bsb3QoaW1pc3MsIGFlcyh4ID0gcmF3LCB5ID0gRjEpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArCiAgbGFicyh4ID0gImluZHYgbWlzc2luZyBkYXRhIHJhdyIsIHkgPSAiaW5kdiBtaXNzaW5nIGRhdGEgRjEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCmxyYXcgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BX3Jhdy5sbWlzcyIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBzZWxlY3QoQ0hSLCBQT1MsIEZfTUlTUykgJT4lCiAgcmVuYW1lKHJhdyA9IEZfTUlTUykKCmxtaXNzIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMS5sbWlzcyIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBzZWxlY3QoQ0hSLCBQT1MsIEZfTUlTUykgJT4lCiAgcmVuYW1lKEYxID0gRl9NSVNTKQoKbG1pc3MgPC0gbGVmdF9qb2luKGxtaXNzLCBscmF3KQoKcDIgPC0gZ2dwbG90KGxtaXNzLCBhZXMoeCA9IHJhdywgeSA9IEYxKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSkgKwogIGxhYnMoeCA9ICJsb2NpIG1pc3NpbmcgZGF0YSByYXciLCB5ID0gImxvY2kgbWlzc2luZyBkYXRhIEYxIikgKwogIHRoZW1lX3N0YW5kYXJkCgptMWIgPC0gbXVsdGlwbG90KHAxLCBwMiwgY29scz0yKQoKYGBgCgpDb21wYXJlIGRlcHRoIGluZGl2aWR1YWxzIGFmdGVyIHJlbW92aW5nIExRIFNOUCBsb2NpIGFuZCBnZW5vdHlwZXMuCgpgYGB7ciBkZXB0aCBGMSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmlyYXcgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BX3Jhdy5pZGVwdGgiLAogICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgc2VsZWN0KElORFYsIE1FQU5fREVQVEgpICU+JQogIHJlbmFtZShyYXcgPSBNRUFOX0RFUFRIKQoKaWRlcHRoIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMS5pZGVwdGgiLAogICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgc2VsZWN0KElORFYsIE1FQU5fREVQVEgpICU+JQogIHJlbmFtZShGMSA9IE1FQU5fREVQVEgpCgppZGVwdGggPC0gbGVmdF9qb2luKGlyYXcsIGlkZXB0aCkKCmdncGxvdChpZGVwdGgsIGFlcyh4ID0gcmF3LCB5ID0gRjEpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNTApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTUwKSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIGluZCByYXciLCB5ID0gIm1lYW4gZGVwdGggaW5kIEYxIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCiMjIyBGaWx0ZXIgMjogR2Vub3R5cGUgY2FsbCByYXRlIGFuZCBhbGxvd2VkIG1pc3NpbmcgZGF0YSBwZXIgaW5kdgoKUmVtb3ZlIGxvY2kgd2l0aCBnZW5vdHlwZSBjYWxsIHJhdGUgPCA1MCUgYW5kIG1pbmltdW0gbWVhbiBkZXB0aCA8IDE1IHJlYWRzIGFjcm9zcyBhbGwgaW5kaXZpZHVhbHMuCgpgYGB7YmFzaCAyYSBnZW5vIDwgNTB9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYyYSAtLW1heC1taXNzaW5nIDAuNSAtLW1pbi1tZWFuRFAgMTUgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCiMgbGlicmFyeSBCTUEtMQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMmEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQTEgLS1rZWVwIGRhdGEvVkNGL0JNQTEuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BMSAtLW1pc3Npbmctc2l0ZQoKIyBsaWJyYXJ5IEJNQS0yCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BMiAtLWtlZXAgZGF0YS9WQ0YvQk1BMi5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEyIC0tbWlzc2luZy1zaXRlCgojIGxpYnJhcnkgQk1BLTMKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEzIC0ta2VlcCBkYXRhL1ZDRi9CTUEzLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQTMgLS1taXNzaW5nLXNpdGUKCiMgQ2FtcGVjaGUKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9DQU1QIC0ta2VlcCBkYXRhL1ZDRi9DQU1QLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQ0FNUC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0NBTVAgLS1taXNzaW5nLXNpdGUKCiMgQ2hhbmRlbGV1ciBTb3VuZAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMmEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0NTIC0ta2VlcCBkYXRhL1ZDRi9DUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0NTLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQ1MgLS1taXNzaW5nLXNpdGUKCiMgQ29ycHVzIENocmlzdGkgQmF5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQ0MgLS1rZWVwIGRhdGEvVkNGL0NDLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQ0MucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9DQyAtLW1pc3Npbmctc2l0ZQoKIyBGbG9yaWRhIEF0bGFudGljCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvRkxBIC0ta2VlcCBkYXRhL1ZDRi9GTEEuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9GTEEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9GTEEgLS1taXNzaW5nLXNpdGUKCiMgRmxvcmlkYSBHdWxmIFNvdXRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvRkxHUyAtLWtlZXAgZGF0YS9WQ0YvRkxHUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0ZMR1MucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9GTEdTIC0tbWlzc2luZy1zaXRlCgojIEZsb3JpZGEgR3VsZiBOb3J0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMmEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0ZMR04gLS1rZWVwIGRhdGEvVkNGL0ZMR04uaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9GTEdOLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvRkxHTiAtLW1pc3Npbmctc2l0ZQoKIyBMb3Vpc2lhbmEKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9MQSAtLWtlZXAgZGF0YS9WQ0YvTEEuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9MQS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0xBIC0tbWlzc2luZy1zaXRlCgojIE1pc3Npc3NpcHBpIFNvdW5kCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvTUlTUyAtLWtlZXAgZGF0YS9WQ0YvTUlTUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL01JU1MucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9NSVNTIC0tbWlzc2luZy1zaXRlCgojIE1vYmlsZSBCYXkKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9NQiAtLWtlZXAgZGF0YS9WQ0YvTUIuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9NQi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL01CIC0tbWlzc2luZy1zaXRlCgpgYGAKCkNvbXBhcmUgZGlzdHJpYnV0aW9uIG9mIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMgcGVyIGxpYnJhcnkuCgpgYGB7ciBsbWlzcyBwZXIgbGliLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBjcmVhdGUgZW1wdHkgbGlzdApsb2NfbWlzc2luZyA8LSBsaXN0KCkKCmZvciAoaSBpbiAxOjMpIHsKICAKICBsaWIgPC0gcGFzdGUoIkJNQSIsIGksIHNlcCA9ICIiKQogIAogIGxvY19taXNzaW5nW1tpXV0gPC0gcmVhZF9kZWxpbShwYXN0ZSgiZGF0YS9WQ0YvIiwgbGliLCAiLmxtaXNzIiwgc2VwID0gIiIpLCBkZWxpbSA9ICJcdCIpICU+JQogICAgc2VsZWN0KENIUiwgUE9TLCBGX01JU1MpICU+JQogICAgbXV0YXRlKExJQiA9IGxpYikKICAKfQoKIyBjcmVhdGUgZGF0YSBmcmFtZSB3aXRoIGFsbCBpbmZvcm1hdGlvbgpsb2NfbWlzc2luZyA8LSBsZHBseShsb2NfbWlzc2luZywgZGF0YS5mcmFtZSkKCmdncGxvdChsb2NfbWlzc2luZywgYWVzKHggPSBGX01JU1MpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDAuNSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWlzc2luZyBkYXRhIHBlciBsb2N1cyIpICsKICBmYWNldF9ncmlkKExJQiB+IC4pICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpGbGFnIGxvY2kgdGhhdCB3ZXJlIG5vdCBjYWxsZWQgaW4gPiA1MCUgb2YgaW5kaXZpZHVhbHMgaW4gYSBnaXZlbiBsaWJyYXJ5LgoKYGBge3J9CgojIGlkZW50aWZ5IGxvY2kgd2l0aCBoaWdoIG1pc3NpbmcgZGF0YSBpbiBlYWNoIGxpYnJhcnkKU05QcyA8LSBmaWx0ZXIobG9jX21pc3NpbmcsIEZfTUlTUyA+IDAuNSkgJT4lCiAgYXJyYW5nZShDSFIsIFBPUykKCmNvdW50KFNOUHMsIExJQikKCkxRbG9jaV9saWIgPC0gU05QcyAlPiUKICBzZWxlY3QoQ0hSLCBQT1MpICU+JQogIHVuaXF1ZSgpCgpgYGAKCkEgdG90YWwgb2YgYHIgTFFsb2NpX2xpYmAgbG9jaSB3ZXJlIGNhbGxlZCBpbiBsZXNzIHRoYW4gNTAlIG9mIGluZGl2aWR1YWxzIGluIG9uZSBvciBtb3JlIGxpYnJhcmllcy4gTG9jaSBiZWluZyBpbmNvbnNpc3RlbnRseSBjYWxsZWQgYmV0d2VlbiBsaWJyYXJpZXMgY2FuIHJlc3VsdCBpbiBsaWJyYXJ5IGVmZmVjdHMuCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIHBlciBzYW1wbGUgbG9jYXRpb24uCgpgYGB7ciBsbWlzcyBwZXIgbG9jLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgY3JlYXRlIGVtcHR5IGxpc3QKbG9jX21pc3NpbmcgPC0gbGlzdCgpCgojIHBvcHMgdG8gbG9vcCBvdmVyCnBvcCA8LSB1bmlxdWUoSW5kX1JBVyRQT1ApCgojIGltcG9ydCBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzCmZvciAocCBpbiBwb3ApIHsKICAKICBsb2NfbWlzc2luZ1tbcF1dIDwtIHJlYWRfZGVsaW0ocGFzdGUoImRhdGEvVkNGLyIsIHAsICIubG1pc3MiLCBzZXAgPSAiIiksIGRlbGltID0gIlx0IikgJT4lCiAgICBzZWxlY3QoQ0hSLCBQT1MsIEZfTUlTUykgJT4lCiAgICBtdXRhdGUoUE9QID0gcCkKICAKfQoKIyBjcmVhdGUgZGF0YSBmcmFtZSB3aXRoIGFsbCBpbmZvcm1hdGlvbgpsb2NfbWlzc2luZyA8LSBsZHBseShsb2NfbWlzc2luZywgZGF0YS5mcmFtZSkgJT4lCiAgc2VsZWN0KC1gLmlkYCkKCmdncGxvdChsb2NfbWlzc2luZywgYWVzKHggPSBGX01JU1MpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjI1KSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIikgKwogIGZhY2V0X2dyaWQoUE9QIH4gLikgKwogIHNjYWxlX3lfc3FydCgpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpGbGFnIGxvY2kgdGhhdCB3ZXJlIG5vdCBjYWxsZWQgaW4gPiA3NSUgb2YgaW5kaXZpZHVhbHMgYXQgYSBnaXZlbiBzYW1wbGUgbG9jYXRpb24uCgpgYGB7cn0KCiMgaWRlbnRpZnkgbG9jaSB3aXRoIGhpZ2ggbWlzc2luZyBkYXRhIGluIGVhY2ggbGlicmFyeQpTTlBzIDwtIGZpbHRlcihsb2NfbWlzc2luZywgRl9NSVNTID4gMC4yNSkgJT4lCiAgYXJyYW5nZShDSFIsIFBPUykKCmNvdW50KFNOUHMsIFBPUCkKCkxRbG9jaV9wb3AgPC0gU05QcyAlPiUKICBzZWxlY3QoQ0hSLCBQT1MpICU+JQogIHVuaXF1ZSgpCgpMUWxvY2kgPC0gYmluZF9yb3dzKExRbG9jaV9saWIsIExRbG9jaV9wb3ApICU+JQogIHVuaXF1ZSgpCgojIFdyaXRlIGNvbnRpZy9wb3NpdGlvbiB0byBmaWxlCndyaXRlLnRhYmxlKExRbG9jaSwgZmlsZSA9ICJkYXRhL1ZDRi9MUV9GMmIubG9jaSIsIAogICAgICAgICAgICBjb2wubmFtZXM9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCmBgYAoKUmVtb3ZlIGxvY2kgdGhhdCB3ZXJlIG5vdCBjb25zaXN0ZW50bHkgY2FsbGVkIGFjcm9zcyBhbGwgbGlicmFyaWVzIGFuZCBzYW1wbGUgbG9jYXRpb25zLgoKYGBge2Jhc2ggZmlsdGVyIG1pc3NpbmcgYnkgbGlifQoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjJhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEuRjJiIC0tZXhjbHVkZS1wb3NpdGlvbnMgZGF0YS9WQ0YvTFFfRjJiLmxvY2kgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyYi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMmIgLS1taXNzaW5nLWluZHYKCmBgYAoKSWRlbnRpZnkgaW5kaXZpZHVhbHMgd2l0aCA+IDI1JSBtaXNzaW5nIGRhdGEKCmBgYHtyIGltaXNzID4gNTAsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTR9CgojIGRldGVybWluZSBjdXRvZmYKaW1pc3MgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BLkYyYi5pbWlzcyIsIAogICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgCgpnZ3Bsb3QoaW1pc3MsIGFlcyh4ID0gRl9NSVNTKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC4yNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHRoZW1lX3N0YW5kYXJkCgppbWlzcyA8LSBpbWlzcyAlPiUKICBmaWx0ZXIoRl9NSVNTID4gMC4yNSkgJT4lCiAgc2VsZWN0KElORFYpCgp3cml0ZS50YWJsZShpbWlzcywgImRhdGEvVkNGL0YyYl9MUS5pbmR2IiwKICAgICAgICAgICAgY29sLm5hbWVzID0gVFJVRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKClJlbW92ZSBmbGFnZ2VkIGluZGl2aWR1YWxzLgoKYGBge2Jhc2ggZmlsdGVyIExRIGluZHZ9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMmIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQS5GMiAtLXJlbW92ZSBkYXRhL1ZDRi9GMmJfTFEuaW5kdiAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjIgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLXNpdGUtbWVhbi1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLW1pc3NpbmctaW5kdgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLWhldAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMiAtLWdlbm8tZGVwdGgKCmBgYAoKQW5hbHl6ZSBzdGF0cyBwb3N0LWZpbHRlcmluZzoKCmBgYHtyIHN0YXRzIEYyLCBmaWcuaGVpZ2h0PTIwLCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGxvYWQgc3RhdHMgZmlsZXMgLS0tLQppbmRfc3RhdHNfRjIgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5GMiIpICU+JQogIHNlcGFyYXRlKElORFYsIGludG8gPSBjKCJTUCIsICJMSUIiLCAiU0FNUExFX0lEIiksIHNlcCA9ICJfIiwgcmVtb3ZlID0gRkFMU0UpCgpsb2Nfc3RhdHNfRjIgPC0gcmVhZC5sb2Muc3RhdHMoZGlyID0gImRhdGEvVkNGLyIsIHZjZiA9ICJCTUEuRjIiKQoKYGBgCgoKIyMjIEZpbHRlciAzOiBGaWx0ZXIgbG9jaSBhbmQgaW5kaXZpZHVhbHMgYmFzZWQgb24gZGVwdGgsIHZhcmlhbmNlIGluIGRlcHRoIGFuZCBnZW5vdHlwZSBjYWxsIHJhdGUKCkRldGVybWluZSBtZWFuIGRlcHRoIGFuZCB2YXJpYW5jZSBwZXIgbG9jdXMgcGVyIGxpYnJhcnkuCgpgYGB7YmFzaCBkZXB0aCBkYXRhIHBlciBsaWJ9CgojIGxpYnJhcnkgQk1BLTEKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQTEgLS1rZWVwIGRhdGEvVkNGL0JNQTEuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BMSAtLXNpdGUtbWVhbi1kZXB0aAoKIyBsaWJyYXJ5IEJNQS0yCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYyLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEyIC0ta2VlcCBkYXRhL1ZDRi9CTUEyLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQTIgLS1zaXRlLW1lYW4tZGVwdGgKCiMgbGlicmFyeSBCTUEtMwp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BMyAtLWtlZXAgZGF0YS9WQ0YvQk1BMy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEzIC0tc2l0ZS1tZWFuLWRlcHRoCgpgYGAKCkNvbXBhcmUgZGlzdHJpYnV0aW9uIG9mIGRlcHRoIGNvdmVyYWdlIHBlciBsb2N1cyBwZXIgbGlicmFyeS4gSWRlbnRpZnkgbG9jaSB0aGF0IGRvIG5vdCBoYXZlIGNvbnNpc3RlbnQgY292ZXJhZ2UgYmV0d2VlbiBsaWJyYXJpZXMgKGNhbiBsZWFkIHRvIGxpYnJhcnkgZWZmZWN0cyksIGFuZC9vciBhY3Jvc3MgaW5kaXZpZHVhbHMuIAoKYGBge3IgZGVwdGggcGVyIGxvY3VzIHBlciBsaWIsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGNyZWF0ZSBlbXB0eSBsaXN0CmxvY19kZXB0aCA8LSBsaXN0KCkKCiMgaW1wb3J0IGRlcHRoIGRhdGEgcGVyIGxvY3VzCmxvY19kZXB0aFtbMV1dIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQTEubGRlcHRoLm1lYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBtdXRhdGUoTElCID0gIkJNQTEiKQoKbG9jX2RlcHRoW1syXV0gPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BMi5sZGVwdGgubWVhbiIsIAogICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JQogIG11dGF0ZShMSUIgPSAiQk1BMiIpCgpsb2NfZGVwdGhbWzNdXSA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi9CTUEzLmxkZXB0aC5tZWFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgbXV0YXRlKExJQiA9ICJCTUEzIikKCiMgY3JlYXRlIGRhdGEgZnJhbWUgd2l0aCBhbGwgaW5mb3JtYXRpb24KbG9jX2RlcHRoIDwtIGxkcGx5KGxvY19kZXB0aCwgZGF0YS5mcmFtZSkKCmdncGxvdChsb2NfZGVwdGgsIGFlcyh4ID0gTUVBTl9ERVBUSCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRILCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBsb2N1cyIpICsKICBmYWNldF9ncmlkKExJQiB+IC4pICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpJZGVudGlmeSBsb2NpIHdpdGggbGFyZ2UgdmFyaWFuY2UgaW4gbWVhbiBkZXB0aCBhY3Jvc3MgbGlicmFyaWVzIGFuZC9vciBpbmRpdmlkdWFscyBieSBjYWxjdWxhdGluZyB0aGUgY29lZmZpY2llbnQgb2YgdmFyaWFuY2UgKFNURC9NRUFOKS4KCmBgYHtyIGNhbGN1bGF0ZSB2YXJpYXRpb24gaW4gZGVwdGgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGNhbGN1bGF0ZSBtZWFuIGRlcHRoIHdlaWdodGVkIGJ5IGxpYnJhcnkKZGVwdGhfY29tcCA8LSBsb2NfZGVwdGggJT4lCiAgZ3JvdXBfYnkoTElCKSAlPiUKICBkaXN0aW5jdChDSFJPTSwgLmtlZXBfYWxsID0gVFJVRSkgJT4lCiAgc2VsZWN0KC1QT1MpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShDSFJPTSkgJT4lCiAgc3VtbWFyaXNlKE1FQU4gPSBtZWFuKE1FQU5fREVQVEgpLAogICAgICAgICAgICBTVEQgPSBzZChNRUFOX0RFUFRIKSkKCiMgbWVhbiBkZXB0aCBhY3Jvc3MgYWxsIGluZGl2aWR1YWxzCnRlbXAgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BLkYyLmxkZXB0aC5tZWFuIiwgCiAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JQogIGRpc3RpbmN0KENIUk9NLCAua2VlcF9hbGwgPSBUUlVFKSAlPiUKICBzZWxlY3QoLVBPUykgJT4lCiAgbXV0YXRlKFNURF9ERVBUSCA9IHNxcnQoVkFSX0RFUFRIKSkKCiMgY2FsY3VsYXRlIGNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbgpkZXB0aF9jb21wIDwtIGxlZnRfam9pbihkZXB0aF9jb21wLCB0ZW1wKSAlPiUKICBtdXRhdGUoQ09FRkZfVkFSX0xJQiA9IFNURC9NRUFOKjEwMCwKICAgICAgICAgQ09FRkZfVkFSX0lORCA9IFNURF9ERVBUSC9NRUFOX0RFUFRIKjEwMCkKCmBgYAoKQ29tcGFyZSBtZWFuIGFjcm9zcyBhbGwgaW5kaXZpZHVhbCB0byBtZWFuIHdlaWdodGVkIGJ5IGxpYnJhcnkgYW5kIGNvZWZmaWNpZW50IG9mIHZhcmlhbmNlIG9mIHJlYWQgZGVwdGggYWNyb3NzIGluZGl2aWR1YWxzIGFuZCBiZXR3ZWVuIGxpYnJhcmllczoKCmBgYHtyIG1lYW4gc3RkIGRlcHRoLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD04LjV9CgpwMSA8LSBnZ3Bsb3QoZGVwdGhfY29tcCwgYWVzKHggPSBNRUFOX0RFUFRILCB5ID0gTUVBTikpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBsb2N1cyIsIHkgPSAibWVhbiB3ZWlnaHRlZCBieSBsaWIiKSArCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJkYXJrcmVkIiwgc2l6ZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKcDIgPC0gZ2dwbG90KGRlcHRoX2NvbXAsIGFlcyh4ID0gQ09FRkZfVkFSX0lORCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gcXVhbnRpbGUoQ09FRkZfVkFSX0lORCwgLjk5KSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJjb2VmZiB2YXIgZGVwdGggYWNyb3NzIGFsbCBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMyA8LSBnZ3Bsb3QoZGVwdGhfY29tcCwgYWVzKHggPSBDT0VGRl9WQVJfSU5ELCB5ID0gQ09FRkZfVkFSX0xJQikpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDIwMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApKSArCiAgbGFicyh4ID0gImNvZWZmIHZhciBkZXB0aCBhY3Jvc3MgYWxsIGluZHYiLCB5ID0gImNvZWZmIHZhciBtZWFuIGRlcHRoIGJldHcgbGliIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwNCA8LSBnZ3Bsb3QoZGVwdGhfY29tcCwgYWVzKHggPSBDT0VGRl9WQVJfTElCKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBxdWFudGlsZShDT0VGRl9WQVJfTElCLCAuOTkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gImNvZWZmIHZhciBkZXB0aCBiZXR3ZWVuIGxpYiIpICsKICB0aGVtZV9zdGFuZGFyZAoKbTNhIDwtIG11bHRpcGxvdChwMSwgcDIsIHAzLCBwNCwgY29scz0yKQoKYGBgCgpJZiBsb2NpIGhhdmUgY29uc2lzdGVudCBjb3ZlcmFnZSBhY3Jvc3MgbG9jaSB0aGUgbWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyBhY3Jvc3MgYWxsIGluZGl2aWR1YWxzIGFuZCB3ZWlnaHRlZCBieSBsaWJyYXJ5IHNob3VsZCBmYWxsIG9uIHRoZSByZWQgZGlhZ29uYWwuIAoKRmxhZyBsb2NpIHRoYXQgaGF2ZSBoaWdoIHZhcmlhdGlvbiBpbiBtZWFuIGNvdmVyYWdlIGJldHdlZW4gaW5kaXZpZHVhbHMgYW5kIGJldHdlZW4gbGlicmFyaWVzLgoKYGBge3IgTFEgbG9jaSB2YXJpYXRpb24gY292ZXJhZ2V9CgojIGlkZW50aWZ5IGxvY2kgaGlnaCB2YXJpYXRpb24gaW4gY292ZXJhZ2UKY29udGlnc192YXIgPC0gZGVwdGhfY29tcCAlPiUKICBmaWx0ZXIoQ09FRkZfVkFSX0xJQiA+IDkwIHwgQ09FRkZfVkFSX0lORCA+IDE1MCkKClNOUHNfdmFyIDwtIGZpbHRlcihsb2NfZGVwdGgsIENIUk9NICVpbiUgY29udGlnc192YXIkQ0hST00pICU+JQogIGRpc3RpbmN0KENIUk9NLCBQT1MpCgojIFdyaXRlIGNvbnRpZy9wb3NpdGlvbiB0byB0ZXh0IGZpbGUsIHVzZSBmaWxlIHdpdGggdmNmdG9vbHMgdG8gcmVtb3ZlIHBvc2l0aW9ucyBmcm9tIGRhdGFzZXQgCndyaXRlLnRhYmxlKFNOUHNfdmFyLCBmaWxlID0gImRhdGEvVkNGL0xRX0YzLmxvY2kiLCAKICAgICAgICAgICAgY29sLm5hbWVzPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKClJlbW92ZSBsb2NpIGZsYWdnZWQgZm9yIGhpZ2ggdmFyaWFuY2UgaW4gZGVwdGggYWNyb3NzIGFsbCBpbmRpdmlkdWFscyBhbmQgYmV0d2VlbiBsaWJyYXJpZXMgKHJlbW92ZXMgbGlicmFyeSBlZmZlY3RzKSwgZmlsdGVyIGxvY2kgd2l0aCBtZWFuIGRlcHRoIDwgMjAgYW5kIGdlbm90eXBlIGNhbGwgcmF0ZSA8IDc1JQoKYGBge2Jhc2ggZmlsdGVyIHZhcmlhbmNlIGluIGNvdmVyYWdlIGxvY2l9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYzYSAtLWV4Y2x1ZGUtcG9zaXRpb25zIGRhdGEvVkNGL0xRX0YzLmxvY2kgLS1taW4tbWVhbkRQIDE1IC0tbWF4LW1pc3NpbmcgMC43NSAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjNhLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYzYSAtLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYzYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GM2EgLS1nZW5vLWRlcHRoCgpgYGAKCkNvbXBhcmUgbWVhbiBkZXB0aCBhbmQgbnVtYmVyIG9mIHNpdGVzIGNhbGxlZCBwZXIgaW5kaXZpZHVhbC4KCmBgYHtyIGlkZXB0aCBzaXRlcyB2cyBkZXB0aCBJLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00LjUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpyZWFkX3RhYmxlMigiZGF0YS9WQ0YvQk1BLkYzYS5pZGVwdGgiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBOX1NJVEVTLCB5ID0gTUVBTl9ERVBUSCkpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc2l6ZSA9IDEuNSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJkYXJrcmVkIiwgc2l6ZSA9IDAuNzUpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZGFya2JsdWUiLCBzaXplID0gMC43NSkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2Ygc2l0ZXMiLCB5ID0gIm1lYW4gcmVhZCBkZXB0aCIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpVc2UgZ2Vub3R5cGUgZGVwdGggZmlsZSB0byBpZGVudGlmeSBpbmRpdmlkdWFscyB3aXRoIGhpZ2ggdmFyaWFuY2UgaW4gcmVhZCBkZXB0aCBhY3Jvc3MgbG9jaS4KCmBgYHtyIHZhcmlhbmNlIGRlcHRoIGluZGl2aWR1YWwgSX0KCiMgbnVtYmVyIG9mIGluZGl2aWR1YWxzCm4gPC0gbnJvdyhpbmRfc3RhdHNfRjIpKzEKCiMgcmVhZCBnZW5vdHlwZSBkZXB0aCAmIGNvZGUgdmFsdWVzIDwgNSBhcyBtaXNzaW5nCmdkZXB0aCA8LSByZWFkX3RhYmxlMigiZGF0YS9WQ0YvQk1BLkYzYS5nZGVwdGgiKSAlPiUKICBzZWxlY3QoLVBPUykgJT4lCiAgZGlzdGluY3QoQ0hST00sIC5rZWVwX2FsbCA9IFRSVUUpICU+JQogIGdhdGhlcihrZXkgPSBJTkRWLCB2YWx1ZSA9IERFUFRILCAzOm4pICU+JQogIG11dGF0ZShERVBUSCA9IGFzLm51bWVyaWMoZ3N1YigtMSwgMCwgREVQVEgpKSwKICAgICAgICAgREVQVEggPSBhcy5udW1lcmljKGdzdWIoIlxcPDFcXD4iLCAwLCBERVBUSCkpLAogICAgICAgICBERVBUSCA9IGFzLm51bWVyaWMoZ3N1YigiXFw8MlxcPiIsIDAsIERFUFRIKSksCiAgICAgICAgIERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDwzXFw+IiwgMCwgREVQVEgpKSwKICAgICAgICAgREVQVEggPSBhcy5udW1lcmljKGdzdWIoIlxcPDRcXD4iLCAwLCBERVBUSCkpKQoKIyBjYWxjdWxhdGUgc3VtbWFyeSBzdGF0aXN0aWNzCmlkZXB0aCA8LSBnZGVwdGggJT4lCiAgZ3JvdXBfYnkoSU5EVikgJT4lCiAgc3VtbWFyaXplKFRPVEFMID0gc3VtKERFUFRIKSwKICAgICAgICAgICAgTUFYID0gbWF4KERFUFRIKSwKICAgICAgICAgICAgTUVBTl9OT04wID0gbWVhbihERVBUSFtERVBUSCA+IDBdKSwKICAgICAgICAgICAgTUVBTiA9IG1lYW4oREVQVEgpLAogICAgICAgICAgICBNRURJQU4gPSBtZWRpYW4oREVQVEgpLAogICAgICAgICAgICBWQVIgPSB2YXIoREVQVEgpLAogICAgICAgICAgICBTVEQgPSBzZChERVBUSCkpICU+JQogIG11dGF0ZShDT0VGRl9WQVIgPSBTVEQvTUVBTiwKICAgICAgICAgUkFUSU9fTUVBTl9NRURJQU4gPSBNRUFOL01FRElBTikKCmlkZXB0aCA8LSBsZWZ0X2pvaW4oaWRlcHRoLCBpbmRfc3RhdHNfRjIpCgpgYGAKCkNvbXBhcmUgdmFyaWFiaWxpdHkgb2YgZGVwdGggd2l0aGluIGluZGl2aWR1YWxzLgoKYGBge3IsIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD0xMH0KCnAxIDwtIGdncGxvdChpZGVwdGgsIGFlcyh4ID0gTUFYLCB5ID0gVE9UQUwpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImF1dG8iLGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxLCBjb2xvciA9ICJkYXJrcmVkIikgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAyIDwtIGdncGxvdChpZGVwdGgsIGFlcyh4ID0gVE9UQUwsIHkgPSBWQVIpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImF1dG8iLGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxLCBjb2xvciA9ICJkYXJrcmVkIikgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAzIDwtIGdncGxvdChpZGVwdGgsIGFlcyhNQVgsIE1FRElBTikpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAiYXV0byIsbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEsIGNvbG9yID0gImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKcDQgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKHggPSBNRUFOLCB5ID0gTUVESUFOKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJhdXRvIixsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSwgY29sb3IgPSAiZGFya3JlZCIpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwNSA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoeCA9IENPRUZGX1ZBUiwgeSA9IFJBVElPX01FQU5fTUVESUFOKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJhdXRvIixsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSwgY29sb3IgPSAiZGFya3JlZCIpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwNiA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoTUVBTikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDE1LCBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwNyA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoTUVESUFOKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMTAsIGNvbG9yID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA4IDwtIGdncGxvdChpZGVwdGgsIGFlcyhSQVRJT19NRUFOX01FRElBTikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA5IDwtIGdncGxvdChpZGVwdGgsIGFlcyhDT0VGRl9WQVIpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAyNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAxMCA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoeCA9IENPRUZGX1ZBUiwgeSA9IE1JU1NfQk1BLkYyKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4yNSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZGFya3JlZCIsIHNpemUgPSAwLjc1KSArCiAgdGhlbWVfc3RhbmRhcmQKCgptM2IgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgY29scz0yKQoKYGBgCgpGbGFnIExRIGluZGl2aWR1YWxzLgoKYGBge3J9CgpMUV9kZXB0aCA8LSBpZGVwdGggJT4lCiBmaWx0ZXIoTUVBTiA8PSAxMCB8IE1FRElBTiA8PSA1KSAlPiUKIHNlbGVjdChJTkRWKQoKTFFfZGVwdGgKIAp3cml0ZS50YWJsZShMUV9kZXB0aCwgImRhdGEvVkNGL0YzX0xRLmluZHYiLAogICAgICAgICAgIGNvbC5uYW1lcyA9IFRSVUUsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKYGBgCgpSZW1vdmUgZmxhZ2dlZCBsb2NpIGFuZCBpbmRpdmlkdWFscy4KCmBgYHtiYXNoIGZpbHRlciB2YXJpYW5jZSBpbiBjb3ZlcmFnZX0KCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYzYS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYzIC0tcmVtb3ZlIGRhdGEvVkNGL0YzX0xRLmluZHYgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYzLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYzIC0tZGVwdGgKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjMgLS1zaXRlLW1lYW4tZGVwdGgKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjMgLS1taXNzaW5nLWluZHYKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjMgLS1taXNzaW5nLXNpdGUKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjMgLS1oZXQKCmBgYAoKQ29tcGFyZSBzdGF0cyBwb3N0LWZpbHRlcmluZzoKCmBgYHtyIHN0YXRzIEYzLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GMyA8LSByZWFkLmluZC5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YiLCB2Y2YgPSAiQk1BLkYzIikgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlNQIiwgIkxJQiIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSkKCmxvY19zdGF0c19GMyA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQS5GMyIpCgojIHBsb3QgbWlzc2luZyBkYXRhIHBlciBpbmR2IC0tLS0KcDEgPC0gZ2dwbG90KGluZF9zdGF0c19GMywgYWVzKHggPSBNSVNTX0JNQS5GMykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuRjMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC4yNSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1pc3NpbmcgZGF0YSBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggcGVyIGluZHYgLS0tLQpwMiA8LSBnZ3Bsb3QoaW5kX3N0YXRzX0YzLCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLkYzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGVwdGggdnMgbWlzc2luZyAtLS0tCnAzIDwtIGdncGxvdChpbmRfc3RhdHNfRjMsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjMsIHkgPSBNSVNTX0JNQS5GMykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjI1KSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWlzc2luZyBkYXRhIHBlciBsb2N1cyAtLS0tCnA0IDwtIGdncGxvdChsb2Nfc3RhdHNfRjMsIGFlcyh4ID0gTUlTU19CTUEuRjMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIlIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWVhbiByZWFkIGRlcHRoIC0tLS0KcDUgPC0gZ2dwbG90KGxvY19zdGF0c19GMywgYWVzKHggPSBNRUFOX0RFUFRIX0JNQS5GMykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRIX0JNQS5GMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gcmVhZCBkZXB0aCBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCByZWFkIGRlcHRoIHZzIG1pc3NpbmcgZGF0YSAtLS0tCnA2IDwtIGdncGxvdChsb2Nfc3RhdHNfRjMsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjMsIHkgPSBNSVNTX0JNQS5GMykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBsb2N1cyIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCm0zIDwtIG11bHRpcGxvdChwMSwgcDIsIHAzLCBwNCwgcDUsIHA2LCBjb2xzPTIpCgpgYGAKCiMjIyBGaWx0ZXIgNDogQWxsZWxlIGJhbGFuY2UKCkFCOiBBbGxlbGUgYmFsYW5jZSBhdCBoZXRlcm96eWdvdXMgc2l0ZXM6IGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgMSByZXByZXNlbnRpbmcgdGhlIHJhdGlvIG9mIHJlYWRzIHNob3dpbmcgdGhlIHJlZmVyZW5jZSBhbGxlbGUgdG8gYWxsIHJlYWRzLCBjb25zaWRlcmluZyBvbmx5IHJlYWRzIGZyb20gaW5kaXZpZHVhbHMgY2FsbGVkIGFzIGhldGVyb3p5Z291cwoKYGBge2Jhc2ggcXVlcnkgSU5GTyBzdGF0cyBJLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKY3V0IC1mOCBCTUEuRjMucmVjb2RlLnZjZiB8IGdyZXAgLW9lICJBQj1bWzpkaWdpdDpdXS5bWzpkaWdpdDpdXVtbOmRpZ2l0Ol1dW1s6ZGlnaXQ6XV0iIHwgc2VkIC1zICdzL0FCPS8vZycgPiBCTUEuRjQuQUIKCmBgYAoKQWxsZWxlIGJhbGFuY2UgaXMgdGhlIHJhdGlvIG9mIHJlYWRzIGZvciByZWZlcmVuY2UgYWxsZWxlIHRvIGFsbCByZWFkcywgY29uc2lkZXJpbmcgb25seSByZWFkcyBmcm9tIGluZGl2aWR1YWxzIGNhbGxlZCBhcyBoZXRlcm96eWdvdXMuIFZhbHVlcyByYW5nZSBmcm9tIDAgLSAxOyBhbGxlbGUgYmFsYW5jZSAoZm9yIHJlYWwgbG9jaSkgc2hvdWxkIGJlIGFwcHJveC4gMC41LiBGaWx0ZXIgU05QcyBmb3Igd2hpY2ggdGhlIHdpdGggYWxsZWxlIGJhbGFuY2UgPCAwLjI1IGFuZCA+IDAuNzUuCgpgYGB7ciBwbG90IEFCLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01fQoKcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuRjQuQUIiLAogICAgICAgICAgIGNvbC5uYW1lcyA9ICJBQiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gQUIpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjUsIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC4yNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuNzUsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpGaWx0ZXIgY29udGlncyB3aXRoIFNOUCBjYWxscyB3aXRoIEFCID4gMC4yNSwgQUIgPiAwLjc1OyByZXRhaW4gbG9jaSB2ZXJ5IGNsb3NlIHRvIDAgKHJldGFpbiBsb2NpIHRoYXQgYXJlIGZpeGVkIHZhcmlhbnRzKS4gUmVtb3ZlIGdlbm90eXBlcyBpZiB0aGUgcXVhbGl0eSBzdW0gb2YgdGhlIHJlZmVyZW5jZSBvciBhbHRlcm5hdGUgYWxsZWxlIHdhcyAwLgoKYGBge2Jhc2gsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgojIHRoaXMgd29ya3MuLi4gbm90IHN1cmUgd2h5IGNhbnQgd3JpdGUgdG8gZmlsZSBpbiB0aGUgZm9sZGVyCnZjZmZpbHRlciAtcyAtZiAiQUIgPiAwLjI1ICYgQUIgPCAwLjc1IHwgQUIgPCAwLjAxIHwgQUIgPiAwLjk5IiAtcyAtZyAiUVIgPiAwIHwgUUEgPiAwIiBCTUEuRjMucmVjb2RlLnZjZiA+IEJNQS5GNC52Y2YgCm1hd2sgJyEvIy8nIEJNQS5GNC52Y2YgfCB3YyAtbAoKYGBgCgpSZW1haW5pbmcgU05QczogNTIsNjEwLgoKCiMjIyBGaWx0ZXIgNTogcXVhbGl0eS9kZXB0aCByYXRpbwoKYGBge2Jhc2h9CgojIHNpdGUgZGVwdGgKY3V0IC1mOCBCTUEuRjQudmNmIHwgZ3JlcCAtb2UgIkRQPVswLTldKiIgfCBzZWQgLXMgJ3MvRFA9Ly9nJyA+IEJNQS40LkRFUFRICgojIHF1YWxpdHkgc2NvcmUKbWF3ayAnIS8jLycgIEJNQS5GNC52Y2YgfCBjdXQgLWYxLDIsNiA+IEJNQS5GNC5sb2NpLnF1YWwKCmBgYAoKQ29tcGFyZSBxdWFsaXR5L2RlcHRoIHJhdGlvLgoKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgZGVwdGgKZGVwdGggPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuNC5ERVBUSCIsCiAgICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gImRlcHRoIikKCiMgcXVhbGl0eSBzY29yZQpxdWFsIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL3RlbXAvQk1BLkY0LmxvY2kucXVhbCIsCiAgICAgICAgICAgICAgICAgICBjb2wubmFtZXMgPSBjKCJsb2N1cyIsICJwb3MiLCAicXVhbCIpKQoKdGVtcCA8LSBiaW5kX2NvbHMocXVhbCwgZGVwdGgpICU+JQogIG11dGF0ZShyYXRpbyA9IHF1YWwvZGVwdGgpCgpnZ3Bsb3QodGVtcCwgYWVzKHggPSByYXRpbykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMjUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJncmV5ODUiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC4yLCBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpSZW1vdmUgbG9jaSB3aXRoIHF1YWxpdHkvZGVwdGggcmF0aW8gPCAwLjIKCmBgYHtiYXNofQoKdmNmZmlsdGVyIC1zIC1mICJRVUFMIC8gRFAgPiAwLjIiIEJNQS5GNC52Y2YgPiBCTUEuRjUudmNmIAoKbWF3ayAnIS8jLycgQk1BLkY1LnZjZiB8IHdjIC1sCgpgYGAKClJlbWFpbmluZyBTTlBzOiAzMSw4ODAuCgojIyMgRmlsdGVyIDY6IG1hcHBpbmcgcXVhbGl0eQoKYGBge2Jhc2ggcXVlcnkgbWFwcGluZyBxdWFsaXR5LCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKY3V0IC1mOCBCTUEuRjUudmNmIHwgZ3JlcCAtb2UgIk1RTT1bMC05XSoiIHwgc2VkIC1zICdzL01RTT0vL2cnID4gQk1BLkY1Lk1RTQoKY3V0IC1mOCBCTUEuRjUudmNmIHwgZ3JlcCAtb2UgIk1RTVI9WzAtOV0qIiB8IHNlZCAtcyAncy9NUU1SPS8vZycgPiBCTUEuRjUuTVFNUgoKYGBgCgpSZW1vdmUgbG9jaSBiYXNlZCBvbiByYXRpbyBvZiBtYXBwaW5nIHF1YWxpdHkgZm9yIHJlZmVyZW5jZSBhbmQgYWx0ZXJuYXRlIGFsbGVsZSwgaS5lLiBzaXRlcyB0aGF0IGhhdmUgYSBoaWdoIGRpc2NyZXBhbmN5IGJldHdlZW4gdGhlIG1hcHBpbmcgcXVhbGl0aWVzIG9mIHR3byBhbGxlbGVzLgoKYGBge3IgcGxvdCBtYXAgcXVhbCByYXRpb3MsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTV9Cgp0ZW1wIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL3RlbXAvQk1BLkY1Lk1RTSIsIGNvbC5uYW1lcyA9ICJNUU0iKQoKbWFwcXVhbCA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi90ZW1wL0JNQS5GNS5NUU1SIiwgY29sLm5hbWVzID0gIk1RTVIiKQoKbWFwcXVhbCA8LSBiaW5kX2NvbHMobWFwcXVhbCwgdGVtcCkgJT4lCiAgbXV0YXRlKHJhdGlvID0gTVFNL01RTVIpCgpmaWx0ZXIgPC0gbWFwcXVhbCAlPiUKICBmaWx0ZXIocmF0aW8gPCAwLjI1IHwgcmF0aW8gPiAxLjc1KQoKZ2dwbG90KG1hcHF1YWwsIGFlcyh4ID0gTVFNLCB5ID0gTVFNUikpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc2l6ZSA9IDEpICsgCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBzaXplID0gMSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gNCwgc2l6ZSA9IDEsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMC41NzEsIHNpemUgPSAxLCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIsIGFlcyh4ID0gTVFNLCB5ID0gTVFNUiksIHNoYXBlID0gMjEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJyZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNjUpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNjUpKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKRmlsdGVyIGxvY2kgd2l0aCBtYXBwaW5nIHF1YWxpdHkgcmF0aW8gPCAwLjI1IGFuZCA+IDEuNzUuCgpgYGB7YmFzaCBmaWx0ZXIgbWFwIHF1YWwgcmF0aW99Cgp2Y2ZmaWx0ZXIgLXMgLWYgIk1RTSAvIE1RTVIgPiAwLjI1ICYgTVFNIC8gTVFNUiA8IDEuNzUiIEJNQS5GNS52Y2YgPiBCTUEuRjYudmNmCgptYXdrICchLyMvJyBCTUEuRjYudmNmIHwgd2MgLWwKCmBgYAoKUmVtYWluaW5nIFNOUHM6IDMwLDE4My4KCiMjIyBGaWx0ZXIgNzogU3RyYW5kIGJhbGFuY2UKClNSRjogTnVtYmVyIG9mIHJlZmVyZW5jZSBvYnNlcnZhdGlvbnMgb24gdGhlIGZvcndhcmQgc3RyYW5kClNBRjogTnVtYmVyIG9mIGFsdGVybmF0ZSBvYnNlcnZhdGlvbnMgb24gdGhlIGZvcndhcmQgc3RyYW5kClNSUjogTnVtYmVyIG9mIHJlZmVyZW5jZSBvYnNlcnZhdGlvbnMgb24gdGhlIHJldmVyc2Ugc3RyYW5kClNBUjogTnVtYmVyIG9mIGFsdGVybmF0ZSBvYnNlcnZhdGlvbnMgb24gdGhlIHJldmVyc2Ugc3RyYW5kCgpgYGB7YmFzaCBxdWVyeSBzdHJhbmRlZG5lc3MsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpjdXQgLWY4IEJNQS5GNi52Y2YgfCBncmVwIC1vZSAiU0FGPVswLTldKiIgfCBzZWQgLXMgJ3MvU0FGPS8vZycgPiBCTUEuRjYuU0FGCgpjdXQgLWY4IEJNQS5GNi52Y2YgfCBncmVwIC1vZSAiU0FSPVswLTldKiIgfCBzZWQgLXMgJ3MvU0FSPS8vZycgPiBCTUEuRjYuU0FSCgpjdXQgLWY4IEJNQS5GNi52Y2YgfCBncmVwIC1vZSAiU1JGPVswLTldKiIgfCBzZWQgLXMgJ3MvU1JGPS8vZycgPiBCTUEuRjYuU1JGCgpjdXQgLWY4IEJNQS5GNi52Y2YgfCBncmVwIC1vZSAiU1JSPVswLTldKiIgfCBzZWQgLXMgJ3MvU1JSPS8vZycgPiBCTUEuRjYuU1JSCgpgYGAKClBhaXJlZCBlbmQgcmVhZHMgc2hvdWxkIG5vdCBvdmVybGFwLCBhbmQgYSBTTlAgc2l0ZSBzaG91bGQgb25seSBiZSBjb3ZlcmVkIGJ5IGVpdGhlciB0aGUgZm9yd2FyZCBvciByZXZlcnNlIHJlYWQgKHN0cmFuZCkuIAoKYGBge3IgcGxvdCBzdHJhbmRlZG5lc3MsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTV9CgpTQUYgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuRjYuU0FGIiwKICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gIlNBRiIpCgpTQVIgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuRjYuU0FSIiwKICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gIlNBUiIpCgpzdHJhbmRzIDwtIGJpbmRfY29scyhTQUYsIFNBUikKClNSRiA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi90ZW1wL0JNQS5GNi5TUkYiLAogICAgICAgICAgICAgICAgICBjb2wubmFtZXMgPSAiU1JGIikKCnN0cmFuZHMgPC0gYmluZF9jb2xzKHN0cmFuZHMsIFNSRikKClNSUiA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi90ZW1wL0JNQS5GNi5TUlIiLAogICAgICAgICAgICAgICAgICBjb2wubmFtZXMgPSAiU1JSIikKCnN0cmFuZHMgPC0gYmluZF9jb2xzKHN0cmFuZHMsIFNSUikgJT4lCiAgbXV0YXRlKHJhdGlvQSA9IFNBRi9TQVIsIHJhdGlvUiA9IFNSRi9TUlIpCgpnZ3Bsb3Qoc3RyYW5kcywgYWVzKHggPSBTQUYsIHkgPSBTQVIpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDAuMSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMTAwLCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKUmVtb3ZlIFNOUCBzaXRlcyB0aGF0IGhhdmUgPiAxMDB4IG1vcmUgZm9yd2FyZCBhbHRlcm5hdGUgcmVhZHMgdGhhbiByZXZlcnNlIGFsdGVybmF0ZSByZWFkcyBhbmQgPiAxMDB4IG1vcmUgZm9yd2FyZCByZXZlcnNlIHJlYWRzIHRoYW4gcmV2ZXJzZSBhbHRlcm5hdGUgcmVhZHMuCgpgYGB7YmFzaCBmaWx0ZXIgc3RyYW5kZWRuZXNzfQoKdmNmZmlsdGVyIC1mICJTQUYgLyBTQVIgPiAxMDAgJiBTUkYgLyBTUlIgPiAxMDAgfCBTQVIgLyBTQUYgPiAxMDAgJiBTUlIgLyBTUkYgPiAxMDAiIC1zIEJNQS5GNi52Y2YgPiBCTUEuRjcudmNmCgptYXdrICchLyMvJyBCTUEuRjcudmNmIHwgd2MgLWwKCmBgYAoKTnVtYmVyIG9mIFNOUHMgcmVtYWluaW5nOiAyNiw3MjIuCgojIyMgRmlsdGVyIDg6IFByb3Blcmx5IHBhaXJlZCBzdGF0dXMKClBBSVJFRDogUHJvcG9ydGlvbiBvZiBvYnNlcnZlZCBhbHRlcm5hdGUgYWxsZWxlcyB3aGljaCBhcmUgc3VwcG9ydGVkIGJ5IHByb3Blcmx5IHBhaXJlZCByZWFkIGZyYWdtZW50cwpQQUlSRURSOiBQcm9wb3J0aW9uIG9mIG9ic2VydmVkIHJlZmVyZW5jZSBhbGxlbGVzIHdoaWNoIGFyZSBzdXBwb3J0ZWQgYnkgcHJvcGVybHkgcGFpcmVkIHJlYWQgZnJhZ21lbnRzCgpJZGVudGlmeSBsb2NpIHdpdGggb25seSB1bnBhaXJlZCByZWFkcyBtYXBwaW5nIHRvIHRoZW0gLSBhbiBhcnRpZmFjdCBpbnRyb2R1Y2VkIGR1ZSBkZSBub3ZvIHJlZmVyZW5jZSBhc3NlbWJseS4gQ29tcGFyZSBudW1iZXIgb2YgcGFpcmVkIHJlYWRzIG1hcHBpbmcgdGhlIHJlZmVyZW5jZSBhbmQgdGhlIGFsdGVybmF0ZSBhbGxlbGVzIHRvIGlkZW50aWZ5IGRpc2NyZXBhbmN5IGluIHRoZSBwYWlyZWQgc3RhdHVzIGZvciByZWFkcyBzdXBwb3J0aW5nIHJlZmVyZW5jZSBhbmQgYWx0ZXJuYXRlIGFsbGVsZXMuCgpgYGB7YmFzaCBmaWx0ZXIgcGFpcmVkIHN0YXR1cywgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCnZjZmZpbHRlciAtZiAiUEFJUkVEID4gMC4wNSAmIFBBSVJFRFIgPiAwLjA1ICYgUEFJUkVEUiAvIFBBSVJFRCA8IDEuNzUgJiBQQUlSRURSIC8gUEFJUkVEID4gMC4yNSB8IFBBSVJFRCA8IDAuMDUgJiBQQUlSRURSIDwgMC4wNSIgLXMgQk1BLkY3LnZjZiA+IEJNQS5GOC52Y2YKCm1hd2sgJyEvIy8nIEJNQS5GOC52Y2YgfCB3YyAtbAoKYGBgCgpOdW1iZXIgb2YgU05QcyBpbiBkYXRhIHNldDogMjMsNzc4LgoKIyMjIEZpbHRlciA5OiBNYXhpbXVtIGRlcHRoICYgUXVhbGl0eQoKSWRlbnRpZnkgZGlzdHJpYnV0aW9uIG9mIGRlcHRoIChiYXNlZCBvbiBvcmlnaW5hbCBkYXRhIHNldCkgdG8gaWRlbnRpZnkgbG9jaSB3aXRoIGV4Y2VzcyBjb3ZlcmFnZS4KCk9yaWdpbmFsIG51bWJlciBvZiBpbmRpdmlkdWFscyBpbiBkYXRhIHNldCBpcyBgciBucm93KGluZF9zdGF0c19yYXcpYCAoSU5GTyBmbGFncyBpbiBmaWx0ZXJlZCBkYXRhIHNldCBhcmUgYXJlIGJhc2VkIG9uIG9yaWdpbmFsIG51bWJlciBvZiBpbmRpdmlkdWFscyBpbiBkYXRhIHNldCkuCgpDcmVhdGUgZmlsZSB3aXRoIHRoZSBvcmlnaW5hbCBzaXRlIGRlcHRoIGFuZCBxdWFsaXR5IHNjb3JlIGZvciBlYWNoIHNpdGU6CgpgYGB7YmFzaCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCiMgc2l0ZSBkZXB0aApjdXQgLWY4IEJNQS5GOC52Y2YgfCBncmVwIC1vZSAiRFA9WzAtOV0qIiB8IHNlZCAtcyAncy9EUD0vL2cnID4gQk1BLkY4LkRFUFRICgojIHF1YWxpdHkgc2NvcmUKbWF3ayAnIS8jLycgIEJNQS5GOC52Y2YgfCBjdXQgLWYxLDIsNiA+IEJNQS5GOC5sb2NpLnF1YWwKCmBgYAoKQ2FsY3VsYXRlIGF2ZXJhZ2UgZGVwdGggYW5kIHN0YW5kYXJkIGRldmlhdGlvbjoKCmBgYHtyIHBsb3QgZGVwdGggdnMgcXVhbCwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NX0KCiMgZGVwdGgKZGVwdGggPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvdGVtcC9CTUEuRjguREVQVEgiLAogICAgICAgICAgICAgICAgICAgIGNvbC5uYW1lcyA9ICJkZXB0aCIpCgojIHF1YWxpdHkgc2NvcmUKcXVhbCA8LSByZWFkLnRhYmxlKCJkYXRhL1ZDRi90ZW1wL0JNQS5GOC5sb2NpLnF1YWwiLAogICAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygibG9jdXMiLCAicG9zIiwgInF1YWwiKSkKCiMgbWVhbiBkZXB0aAptZWFuX2RlcHRoIDwtIG1lYW4oZGVwdGgkZGVwdGgpCgojIHN0YW5kYXJkIGRldmlhdGlvbgpzdGQgPC0gc2QoZGVwdGgkZGVwdGgpCgojIGNhbGN1bGF0ZSBjdXRvZmYKY3V0b2ZmIDwtIHN1bShtZWFuX2RlcHRoICsgKDIqc3RkKSkKCiMgaWRlbnRpZnkgU05QcyB3aXRoIGV4Y2VzcyAoaS5lLiBkZXB0aCA+IG1lYW4gZGVwdGggKyAxIHN0YW5kYXJkIGRldmlhdGlvbgojIGFuZCBxdWFsaXR5IHNjb3JlIDwgMnggdGhlIGRlcHRoIGF0IHRoYXQgc2l0ZQpkZiA8LSBiaW5kX2NvbHMocXVhbCwgZGVwdGgpICU+JQogIG11dGF0ZShxdWFsY3V0b2ZmID0gMipkZXB0aCkKCnJlbW92ZWxvYyA8LSBkZiAlPiUKICBmaWx0ZXIoZGVwdGggPiBjdXRvZmYpICU+JQogIGZpbHRlcihxdWFsIDwgMipkZXB0aCkKCiMgcGxvdApnZ3Bsb3QoZGYsIGFlcyh4ID0gZGVwdGgsIHkgPSBxdWFsKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxKSArCiAgZ2VvbV9wb2ludChkYXRhID0gcmVtb3ZlbG9jLCBhZXMoeCA9IGRlcHRoLCB5ID0gcXVhbCksIHNoYXBlID0gMjEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJyZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBkZiwgYWVzKHggPSBkZXB0aCwgeSA9IHF1YWxjdXRvZmYpLCBjb2xvciA9ICJibHVlIiwgIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY3V0b2ZmLCBjb2xvciA9ICJibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKTFEgPC0gcmVtb3ZlbG9jICU+JQogIHNlbGVjdChsb2N1cywgcG9zKQoKd3JpdGUudGFibGUoTFEsICJkYXRhL1ZDRi90ZW1wL0xRX0Y5LmxvY2kiLCAKICAgICAgICAgICAgY29sLm5hbWVzID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKYGBgCgpNZWFuIGRlcHRoIHBlciBsb2N1cyAoYWNyb3NzIGFsbCBpbmRpdnVhbHMpIGlzIGByIG1lYW5fZGVwdGhgIGFuZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIGByIHN0ZGAuIAoKRmlsdGVyIFNOUCBzaXRlIHdpdGggZGVwdGggPiBtZWFuIGRlcHRoICsgMSBzdGFuZGFyZCBkZXZpYXRpb24gPSBgciBzdW0obWVhbl9kZXB0aCArIDIqc3RkKWAgYW5kIHRoYXQgaGF2ZSBxdWFsaXR5IHNjb3JlcyA8IDJ4IHRoZSBkZXB0aCBhdCB0aGF0IHNpdGUgYW5kIG91dHB1dCBkZXB0aCBwZXIgc2l0ZS4KCmBgYHtiYXNoIGZpbHRlciBkZXB0aCBxdWFsLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKdmNmdG9vbHMgLS12Y2YgIGRhdGEvVkNGL3RlbXAvQk1BLkY4LnZjZiAtLWV4Y2x1ZGUtcG9zaXRpb25zIGRhdGEvVkNGL3RlbXAvTFFfRjkubG9jaSAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbCAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQS5GOWEKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkY5YS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOWEgLS1zaXRlLW1lYW4tZGVwdGgKCmBgYAoKQ29tcGFyZSB0aGUgZGlzdHJpYnV0aW9uIG9mIG1lYW4gZGVwdGggcGVyIHNpdGUgYXZlcmFnZWQgYWNyb3NzIGluZGl2aWR1YWxzIHRvIGRldGVybWluZSBjdXQtb2ZmIHZhbHVlIG9mIHNpdGVzIHdpdGggZXhjZXNzaXZlbHkgaGlnaCBkZXB0aCBpbmRpY2F0aXZlIG9mIHBhcmFsb2dzL211bHRpY29weSBsb2NpLgoKYGBge3IgcGxvdCBkZXB0aCBkaXN0LCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBjYWxjdWxhdGUgbWVhbiBkZXB0aCBwZXIgc2l0ZSAoMTc3IGluZGl2aWR1YWxzKQpyZWFkLnRhYmxlKCJkYXRhL1ZDRi9CTUEuRjlhLmxkZXB0aC5tZWFuIiwKICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBNRUFOX0RFUFRIKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMjAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEgsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IHF1YW50aWxlKE1FQU5fREVQVEgsIC45NSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gcXVhbnRpbGUoTUVBTl9ERVBUSCwgLjk5KSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHNjYWxlX3lfc3FydCgpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgc2l0ZSIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpDaG9vc2UgY3V0LW9mZiBmb3IgbWF4aW11bSBtZWFuIHJlYWQgZGVwdGggPSAzMDAuCgpgYGB7YmFzaCBmaWx0ZXIgbWF4IGRlcHRofQoKdmNmdG9vbHMgLS12Y2YgIGRhdGEvVkNGL3RlbXAvQk1BLkY4LnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQS5GOSAtLW1heC1tZWFuRFAgMzAwIC0tZXhjbHVkZS1wb3NpdGlvbnMgZGF0YS9WQ0YvdGVtcC9MUV9GOS5sb2NpIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsIAoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjkucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjkgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOSAtLXNpdGUtbWVhbi1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOSAtLW1pc3NpbmctaW5kdgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOSAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GOSAtLWhldAoKYGBgCgpEZXB0aCBkaXN0cmlidXRpb24gcGVyIGxvY3VzIGFmdGVyIGZpbHRlcmluZzoKCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpyZWFkX3RhYmxlMigiZGF0YS9WQ0YvQk1BLkY5LmxkZXB0aC5tZWFuIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gTUVBTl9ERVBUSCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpBbmFseXplIHN0YXRzIHBvc3QtZmlsdGVyaW5nOgoKYGBge3Igc3RhdHMgRjksIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GOSA8LSByZWFkLmluZC5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YiLCB2Y2YgPSAiQk1BLkY5IikgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlNQIiwgIkxJQiIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSkKCmxvY19zdGF0c19GOSA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQS5GOSIpCgojIHBsb3QgbWlzc2luZyBkYXRhIHBlciBpbmR2IC0tLS0KcDEgPC0gZ2dwbG90KGluZF9zdGF0c19GOSwgYWVzKHggPSBNSVNTX0JNQS5GOSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuRjksIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC4yNSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1pc3NpbmcgZGF0YSBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggcGVyIGluZHYgLS0tLQpwMiA8LSBnZ3Bsb3QoaW5kX3N0YXRzX0Y5LCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLkY5KSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkY5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGVwdGggdnMgbWlzc2luZyAtLS0tCnAzIDwtIGdncGxvdChpbmRfc3RhdHNfRjksIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjksIHkgPSBNSVNTX0JNQS5GOSkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkY5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GOSwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjI1KSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWlzc2luZyBkYXRhIHBlciBsb2N1cyAtLS0tCnA0IDwtIGdncGxvdChsb2Nfc3RhdHNfRjksIGFlcyh4ID0gTUlTU19CTUEuRjkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GOSwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIlIG1pc3NpbmcgZGF0YSBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkaXN0cmlidXRpb24gbWVhbiByZWFkIGRlcHRoIC0tLS0KcDUgPC0gZ2dwbG90KGxvY19zdGF0c19GOSwgYWVzKHggPSBNRUFOX0RFUFRIX0JNQS5GOSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkY5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggdnMgbWlzc2luZyBkYXRhIC0tLS0KcDYgPC0gZ2dwbG90KGxvY19zdGF0c19GOSwgYWVzKHggPSBNRUFOX0RFUFRIX0JNQS5GOSwgeSA9IE1JU1NfQk1BLkY5KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuRjksIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLkY5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDAuMSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gZGVwdGggcGVyIGxvY3VzIiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKbTMgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIGNvbHM9MikKCmBgYAoKRGF0YSBzZXQgY29udGFpbnMgYHIgbnJvdyhsb2Nfc3RhdHNfRjkpYCBTTlAgc2l0ZXMgYW5kIGByIG5yb3coaW5kX3N0YXRzX0Y5KWAgaW5kaXZpZHVhbHMuCgoKIyMjIEZpbHRlciAxMDogTWlzc2luZyBkYXRhIGFuZCBtaW5pbXVtIGRlcHRoIHBlciBsb2N1cwoKRmlsdGVyIGxvY2kgd2l0aCBtZWFuIHJlYWQgZGVwdGggPCAxNSBhbmQgZ2Vub3R5cGUgY2FsbCByYXRlIDwgOTAlLgoKYGBge2Jhc2ggZ2VubyA5MCBtZWFuRFAgMTV9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GOS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYxMCAtLW1pbi1tZWFuRFAgMTUgLS1tYXgtbWlzc2luZyAwLjkgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTAgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTAucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEwIC0tc2l0ZS1tZWFuLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTAgLS1taXNzaW5nLWluZHYKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEwLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxMCAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTAucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEwIC0taGV0CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTAgLS1oYXJkeQoKYGBgCgojIyMgRmlsdGVyIDExOiBFeGNlc3MgaGV0ZXJvenlnb3NpdHkKCklkZW50aWZ5IFNOUHMgd2l0aCBtb3JlIHRoYW4gMC41IGhldGVyb3p5Z29zaXR5IGFuZCBzaWduaWZpY2FudC4KCmBgYHtyfQoKIyBjYWxjdWxhdGUgb2JzZXJ2ZWQgaGV0ZXJvenlnb3NpdHkKaHdlIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMTAuaHdlIiwgCiAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSkgJT4lCiAgc2VsZWN0KC1DaGlTcV9IV0UpICU+JQogIHNlcGFyYXRlKGBPQlMuSE9NMS5IRVQuSE9NMi5gLCAKICAgICAgICAgICBpbnRvID0gYygib2JzX2hvbTEiLCAib2JzX2hldCIsICJvYnNfaG9tMiIpLCAKICAgICAgICAgICBzZXAgPSAiLyIsIGNvbnZlcnQgPSBUUlVFKSAlPiUKICBzZXBhcmF0ZShgRS5IT00xLkhFVC5IT00yLmAsIAogICAgICAgICAgIGludG8gPSBjKCJleHBfaG9tMSIsICJleHBfaGV0IiwgImV4cF9ob20yIiksIAogICAgICAgICAgIHNlcCA9ICIvIiwgY29udmVydCA9IFRSVUUpICU+JSAgIAogIG11dGF0ZShIbyA9IG9ic19oZXQvKG9ic19ob20xICsgb2JzX2hvbTIgKyBvYnNfaGV0KSwKICAgICAgICAgSGUgPSBleHBfaGV0LyhleHBfaG9tMSArIGV4cF9ob20yICsgZXhwX2hldCkpICU+JQogIHNlbGVjdChDSFIsIFBPUywgb2JzX2hvbTEsIGV4cF9ob20xLCBvYnNfaG9tMiwgZXhwX2hvbTIsIFBfSEVUX0RFRklDSVQsIG9ic19oZXQsIGV4cF9oZXQsIFBfSEVUX0VYQ0VTUywgSG8sIEhlLCBQX0hXRSkKCmBgYAoKRGlzdHJpYnV0aW9uIG9mIG9ic2VydmVkIGhldGVyb3p5Z29zaXR5LgoKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NH0KCmdncGxvdChod2UsIGFlcyh4ID0gSG8pKSArIAogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC41LCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm9ic2VydmVkIGhldGVyb3p5Z29zaXR5IikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCklkZW50aWZ5IGxvY2kgd2l0aCBoZXRlcm96eWdvc2l0eSA+IDAuNSwgdGhlbiBjb3JyZWN0IHAtdmFsdWVzIGZvciBtdWx0aXBsZSBjb21wYXJpc29ucyB1c2luZyBCZW5qYW1pbmktSG9jaGJlcmcgbWV0aG9kLgoKYGBge3J9CgojIGlkZW50aWZ5IGNvbnRpZ3Mgd2l0aCBTTlBzIHdpdGggSG8gPiAwLjUgJiBzaWduaWZpY2FudApleGNlc3NfaHdlIDwtIGh3ZSAlPiUKICBmaWx0ZXIoSG8gPiAwLjUpICU+JQogIG11dGF0ZShwX2FkaiA9IHAuYWRqdXN0KFBfSEVUX0VYQ0VTUyksIG1ldGhvZCA9ICJmZHIiKSAlPiUKICBmaWx0ZXIocF9hZGogPCAwLjAxKQoKY29udGlncyA8LSBod2UgJT4lCiAgZmlsdGVyKENIUiAlaW4lIGV4Y2Vzc19od2UkQ0hSKSAlPiUKICBzZWxlY3QoQ0hSKSAlPiUKICB1bmlxdWUoKQoKIyBpZGVudGlmeSBhbGwgU05QcyBvbiBjb250aWdzClNOUHMgPC0gaHdlICU+JQogIGZpbHRlcihDSFIgJWluJSBjb250aWdzJENIUikgJT4lCiAgc2VsZWN0KENIUiwgUE9TKQoKIyBWaWV3KGNvbnRpZ3MpCgojIFdyaXRlIGNvbnRpZy9wb3NpdGlvbiB0byB0ZXh0IGZpbGUsIHVzZSBmaWxlIHdpdGggdmNmdG9vbHMgdG8gcmVtb3ZlIHBvc2l0aW9ucyBmcm9tIGRhdGFzZXQgCndyaXRlLnRhYmxlKFNOUHMsIGZpbGUgPSAiZGF0YS9WQ0YvaGV0ZXhjZXNzLmxvY2kiLCAKICAgICAgICAgICAgY29sLm5hbWVzPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKClJlbW92ZSBTTlBzIHdpdGggZXhjZXNzIGhldGVyb3p5Z29zaXR5IGFuZCBjb250aWdzIHdpdGggbW9yZSB0aGFuIG9uZSBTTlAgdy9leGNlc3MgaGV0ZXJvenlnb3NpdHkuCgpgYGB7YmFzaH0KCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYxMSAtLWV4Y2x1ZGUtcG9zaXRpb25zIGRhdGEvVkNGL2hldGV4Y2Vzcy5sb2NpIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjExIC0tZGVwdGgKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxMSAtLXNpdGUtbWVhbi1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjExIC0tbWlzc2luZy1pbmR2CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTEgLS1taXNzaW5nLXNpdGUKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxMSAtLWhldAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjExIC0tZ2Vuby1kZXB0aAoKYGBgCgpWaXN1YWxpemUgc3RhdHM6CgpgYGB7ciBzdGF0cyBGMTIsIGZpZy5oZWlnaHQ9MjAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GMTEgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5GMTEiKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiU1AiLCAiTElCIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFKQoKbG9jX3N0YXRzX0YxMSA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQS5GMTEiKQoKYGBgCgpEYXRhIHNldCBjb250YWlucyBgciBucm93KGxvY19zdGF0c19GMTEpYCBTTlAgc2l0ZXMgYW5kIGByIG5yb3coaW5kX3N0YXRzX0YxMSlgIGluZGl2aWR1YWxzLgoKIyMjIEZpbHRlciAxMjogRmlsdGVyIExRIGluZGl2aWR1YWxzCgpDb21wYXJlIG1lYW4gZGVwdGggYW5kIG51bWJlciBvZiBzaXRlcyBjYWxsZWQgcGVyIGluZGl2aWR1YWwuCgpgYGB7ciBpZGVwdGggc2l0ZXMgdnMgZGVwdGgsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpyZWFkX3RhYmxlMigiZGF0YS9WQ0YvQk1BLkYxMS5pZGVwdGgiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBOX1NJVEVTLCB5ID0gTUVBTl9ERVBUSCkpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIHNpdGVzIiwgeSA9ICJtZWFuIHJlYWQgZGVwdGgiKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKVXNlIGdlbm90eXBlIGRlcHRoIGZpbGUgdG8gaWRlbnRpZnkgaW5kaXZpZHVhbHMgd2l0aCBoaWdoIHZhcmlhbmNlIGluIHJlYWQgZGVwdGggYWNyb3NzIGxvY2kuCgpgYGB7ciB2YXJpYW5jZSBkZXB0aCBpbmRpdmlkdWFsfQoKIyBudW1iZXIgb2YgaW5kaXZpZHVhbHMKbiA8LSBucm93KGluZF9zdGF0c19GMTEpKzEKCiMgcmVhZCBnZW5vdHlwZSBkZXB0aCAmIGNvZGUgdmFsdWVzIDwgNSBhcyBtaXNzaW5nLCByZXRhaW4gb25seSBvbmUgbG9jdXMgcGVyIGNvbnRpZwpnZGVwdGggPC0gcmVhZF90YWJsZTIoImRhdGEvVkNGL0JNQS5GMTEuZ2RlcHRoIikgJT4lCiAgc2VsZWN0KC1QT1MpICU+JQogIGRpc3RpbmN0KENIUk9NLCAua2VlcF9hbGwgPSBUUlVFKSAlPiUKICBnYXRoZXIoa2V5ID0gSU5EViwgdmFsdWUgPSBHREVQVEgsIDI6bikgJT4lCiAgbXV0YXRlKEdERVBUSCA9IGFzLm51bWVyaWMoZ3N1YigtMSwgMCwgR0RFUFRIKSkpICU+JQogIG11dGF0ZShERVBUSCA9IEdERVBUSCkgJT4lCiAgbXV0YXRlKERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDwxXFw+IiwgMCwgREVQVEgpKSkgJT4lCiAgbXV0YXRlKERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDwyXFw+IiwgMCwgREVQVEgpKSkgJT4lCiAgbXV0YXRlKERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDwzXFw+IiwgMCwgREVQVEgpKSkgJT4lCiAgbXV0YXRlKERFUFRIID0gYXMubnVtZXJpYyhnc3ViKCJcXDw0XFw+IiwgMCwgREVQVEgpKSkgJT4lCiAgbXV0YXRlKE1JU1NJTkcgPSBpZmVsc2UoREVQVEggPT0gMCwgIm1pc3NpbmciLCAiZ2Vub3R5cGVkIikpICU+JQogIG11dGF0ZShHREVQVEhCSU4gPSBjdXQoR0RFUFRILCAKICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoMCwgNSwgMTAsIDI1LCA1MCwgMTAwLCA1MDAsIG1heChHREVQVEgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIjw1IiwgIjMtMTAiLCAiMTAtMjUiLCAiMjUtNTAiLCAiNTAtMTAwIiwgIjEwMC01MDAiLCAiPjUwMCIpKSkgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlNQIiwgIkxJQiIsICJTQU1QTEVfSUQiKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSwgZXh0cmEgPSAibWVyZ2UiKSAlPiUKICBtdXRhdGUoTElCID0gc3RyX3JlcGxhY2VfYWxsKExJQiwgIjFBLioiLCAiQk1BMSIpLAogICAgICAgICBMSUIgPSBzdHJfcmVwbGFjZV9hbGwoTElCLCAiMUIuKiIsICJCTUExIiksCiAgICAgICAgIExJQiA9IHN0cl9yZXBsYWNlX2FsbChMSUIsICIyQS4qIiwgIkJNQTIiKSwKICAgICAgICAgTElCID0gc3RyX3JlcGxhY2VfYWxsKExJQiwgIjJCLioiLCAiQk1BMiIpLAogICAgICAgICBMSUIgPSBzdHJfcmVwbGFjZV9hbGwoTElCLCAiM0EuKiIsICJCTUEzIiksCiAgICAgICAgIExJQiA9IHN0cl9yZXBsYWNlX2FsbChMSUIsICIzQi4qIiwgIkJNQTMiKSkKCmdkZXB0aCA8LSBsZWZ0X2pvaW4oZ2RlcHRoLCBTYW1wbGVJbmZvLCBieSA9ICJTQU1QTEVfSUQiKQoKYGBgCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBkZXB0aC4KCmBgYHtyIGdlbm90eXBlIGRlcHRoIGhlYXRtYXAgcG9wLCBmaWcuaGVpZ2h0PTIwLCBmaWcud2lkdGg9MjB9CgojIHdvdWxkIG5lZWQgdG8gam9pbiB3aXRoIFNhbXBsZSBJbmZvIHRvIGdldCBwb3Agc3BlY2lmaWNhdGlvbnMKZ2dwbG90KGdkZXB0aCwgYWVzKHggPSBJTkRWLCB5ID0gQ0hST00pKSArCiAgZ2VvbV90aWxlKGFlcyhmaWxsID0gR0RFUFRIQklOKSkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSwgb3B0aW9uID0gInZpcmlkaXMiLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gJ2dlbm90eXBlIGRlcHRoJywKICAgICAgICAgICAgICAgICAgICAgZGlzY3JldGUgPSBUUlVFKSArCiAgZmFjZXRfZ3JpZCguIH4gUE9QLCBzcGFjZSA9ICJmcmVlIiwgc2NhbGVzID0gImZyZWUiLCBkcm9wID0gVFJVRSkgKwogIGxhYnMoeCA9ICJpbmRpdmlkdWFsIiwgeSA9ICJsb2N1cyIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKYGBgCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBkZXB0aCBvZiBpbmRpdmlkdWFscyBncm91cGVkIGJ5IGxpYnJhcnkuCgpgYGB7ciBnZW5vdHlwZSBkZXB0aCBoZWF0bWFwIGxpYiwgZmlnLmhlaWdodD0yMCwgZmlnLndpZHRoPTIwfQoKZ2dwbG90KGdkZXB0aCwgYWVzKHggPSBJTkRWLCB5ID0gQ0hST00pKSArIAogIGdlb21fdGlsZShhZXMoZmlsbCA9IEdERVBUSEJJTikpICsgCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpcmVjdGlvbiA9IC0xLCBvcHRpb24gPSAidmlyaWRpcyIsCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAnZ2Vub3R5cGUgZGVwdGgnLAogICAgICAgICAgICAgICAgICAgICBkaXNjcmV0ZSA9IFRSVUUpICsKICBmYWNldF9ncmlkKC4gfiBMSUIsIHNwYWNlID0gImZyZWUiLCBzY2FsZXMgPSAiZnJlZSIsIGRyb3AgPSBUUlVFKSArCiAgbGFicyh4ID0gImluZGl2aWR1YWwiLCB5ID0gImxvY3VzIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCgpgYGAKCkNvbXBhcmUgZGlzdHJpYnV0aW9uIG9mIGdlbm90eXBlIGRlcHRocyAoYWNyb3NzIGFsbCBpbmRpdmlkdWFscykuCgpgYGB7ciBkaXN0cmlidXRpb24gZ2Vub3R5cGUgZGVwdGhzLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTUuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCnRlbXAgPC0gY291bnQoZ2RlcHRoLCBHREVQVEhCSU4pCgpnZ3Bsb3QodGVtcCwgYWVzKHggPSBHREVQVEhCSU4sIHkgPSBuKSkgKwogIGdlb21fYmFyKHN0YXQ9ICJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCklkZW50aWZ5IHZhcmlhbmNlIGluIGRlcHRoIHcvaW4gaW5kaXZpZHVhbHMuCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTl9CgojIGNhbGN1bGF0ZSBzdW1tYXJ5IHN0YXRpc3RpY3MKaWRlcHRoIDwtIGdkZXB0aCAlPiUKICBncm91cF9ieShJTkRWKSAlPiUKICBzdW1tYXJpemUoVE9UQUwgPSBzdW0oREVQVEgpLAogICAgICAgICAgICBNQVggPSBtYXgoREVQVEgpLAogICAgICAgICAgICBNRUFOID0gbWVhbihERVBUSCksCiAgICAgICAgICAgIE1FRElBTiA9IG1lZGlhbihERVBUSCksCiAgICAgICAgICAgIFZBUiA9IHZhcihERVBUSCksCiAgICAgICAgICAgIFNURCA9IHNkKERFUFRIKSkgJT4lCiAgbXV0YXRlKENPRUZGX1ZBUiA9IFNURC9NRUFOLAogICAgICAgICBSQVRJT19NRUFOX01FRElBTiA9IE1FQU4vTUVESUFOKQoKcDEgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKHggPSBNRUFOLCB5ID0gTUVESUFOKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJhdXRvIixsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSwgY29sb3IgPSAiZGFya3JlZCIpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwMiA8LSBnZ3Bsb3QoaWRlcHRoLCBhZXMoeCA9IE1BWCwgeSA9IFRPVEFMKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEsIGNvbG9yID0gImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKcDMgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKHggPSBUT1RBTCwgeSA9IFZBUikpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAiYXV0byIsbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEsIGNvbG9yID0gImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsKICB0aGVtZV9zdGFuZGFyZAoKcDQgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKE1FRElBTikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICB0aGVtZV9zdGFuZGFyZAoKcDUgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKFJBVElPX01FQU5fTUVESUFOKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICB0aGVtZV9zdGFuZGFyZAoKcDYgPC0gZ2dwbG90KGlkZXB0aCwgYWVzKENPRUZGX1ZBUikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIHRoZW1lX3N0YW5kYXJkCgptMTRiIDwtIG11bHRpcGxvdChwMSwgcDIsIHAzLCBwNCwgcDUsIHA2LCBjb2xzPTIpCgpgYGAKCkNvbXBhcmUgZGVwdGgsIG1pc3NpbmcgZGF0YSBhbmQgaW5kaXZpZHVhbCBoZXRlcm96eWdvc2l0eSBsZXZlbHMuCgpgYGB7ciBpc3RhdHMsIGZpZy5oZWlnaHQ9MTgsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmltaXNzIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjExLmltaXNzIikgJT4lCiAgc2VsZWN0KElORFYsIE5fREFUQSwgRl9NSVNTKQoKaXN0YXRzIDwtIGxlZnRfam9pbihpZGVwdGgsIGltaXNzKQoKRmlzIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjExLmhldCIpICU+JQogIHNlbGVjdCgtTl9TSVRFUykKCmlzdGF0cyA8LSBsZWZ0X2pvaW4oaXN0YXRzLCBGaXMpCgpwMSA8LSBnZ3Bsb3QoaXN0YXRzLCBhZXMoeCA9IE1FQU4sIHkgPSBGX01JU1MsIGZpbGwgPSBgRmApKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBzaXplID0gMiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpcmVjdGlvbiA9IDEsIG9wdGlvbiA9ICJ2aXJpZGlzIiwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICdGaXMnLCBkaXNjcmV0ZSA9IEZBTFNFKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAyIDwtIGdncGxvdChpc3RhdHMsIGFlcyh4ID0gQ09FRkZfVkFSLCB5ID0gTUVBTiwgZmlsbCA9IEZfTUlTUykpICsKIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgc2l6ZSA9IDIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSwgb3B0aW9uID0gInZpcmlkaXMiLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gJyUgbWlzc2luZycsIGRpc2NyZXRlID0gRkFMU0UpICsKICB0aGVtZV9zdGFuZGFyZAoKcDMgPC0gZ2dwbG90KGlzdGF0cywgYWVzKHggPSBgTyhIT00pYCwgeSA9IE1FQU4sIGZpbGwgPSBGX01JU1MpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBzaXplID0gMiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpcmVjdGlvbiA9IC0xLCBvcHRpb24gPSAidmlyaWRpcyIsCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAnbWVhbiByZWFkIGRlcHRoJywgZGlzY3JldGUgPSBGQUxTRSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwNCA8LSBnZ3Bsb3QoaXN0YXRzLCBhZXMoeCA9IE1FQU4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMCwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA1IDwtIGdncGxvdChpc3RhdHMsIGFlcyh4ID0gYEZgLCB5ID0gTUVBTiwgZmlsbCA9IEZfTUlTUykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIHNpemUgPSAyLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEsIG9wdGlvbiA9ICJ2aXJpZGlzIiwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICclIG1pc3NpbmcnLCBkaXNjcmV0ZSA9IEZBTFNFKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA2IDwtIGdncGxvdChpc3RhdHMsIGFlcyh4ID0gYEZgLCB5ID0gQ09FRkZfVkFSLCBmaWxsID0gRl9NSVNTKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgc2l6ZSA9IDIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSwgb3B0aW9uID0gInZpcmlkaXMiLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gJyUgbWlzc2luZycsIGRpc2NyZXRlID0gRkFMU0UpICsKICB0aGVtZV9zdGFuZGFyZAoKcDcgPC0gZ2dwbG90KGlzdGF0cywgYWVzKHggPSBgRmAsIHkgPSBSQVRJT19NRUFOX01FRElBTiwgZmlsbCA9IEZfTUlTUykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIHNpemUgPSAyLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEsIG9wdGlvbiA9ICJ2aXJpZGlzIiwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICclIG1pc3NpbmcnLCBkaXNjcmV0ZSA9IEZBTFNFKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMC44LCA0KSkgKwogIHRoZW1lX3N0YW5kYXJkCgpwOCA8LSBnZ3Bsb3QoaXN0YXRzLCBhZXMoeCA9IEZfTUlTUykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIHRoZW1lX3N0YW5kYXJkCgoKbTE0YiA8LSBtdWx0aXBsb3QocDEsIHAyLCBwMywgcDQsIHA1LCBwNiwgcDcsIHA4LCBjb2xzPTIpCgpgYGAKCkZsYWcgbG93IHF1YWxpdHkgaW5kaXZpZHVhbHMKCmBgYHtyfQoKIyBWaWV3KGlzdGF0cykKCkxRX2luZCA8LSBpc3RhdHMgJT4lCiAgIGZpbHRlcihgRmAgPiAuOSB8IGBGYCA8IC0uMjUpICU+JQogICBzZWxlY3QoSU5EVikKCndyaXRlLnRhYmxlKExRX2luZCwgImRhdGEvVkNGL0YxMl9MUS5pbmR2IiwKICAgICAgICAgICAgY29sLm5hbWVzID0gVFJVRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKCiMjIyBGaWx0ZXIgMTM6IE1pc3NpbmcgZGF0YSBieSBzYW1wbGUgbG9jYXRpb24KCmBgYHtiYXNoIG1pc3NpbmcgYnkgc2FtcGxlIGxvY2F0fQoKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjExLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9CTUEuRjEyIC0tcmVtb3ZlIGRhdGEvVkNGL0YxMl9MUS5pbmR2IC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgojIENhbXBlY2hlCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQ0FNUCAtLWtlZXAgZGF0YS9WQ0YvQ0FNUC5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQ0FNUC5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0NBTVAgLS1taXNzaW5nLXNpdGUKCiMgQ2hhbmRlbGV1ciBTb3VuZAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0NTIC0ta2VlcCBkYXRhL1ZDRi9DUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQ1MucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9DUyAtLW1pc3Npbmctc2l0ZQoKIyBDb3JwdXMgQ2hyaXN0aSBCYXkKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEyLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9DQyAtLWtlZXAgZGF0YS9WQ0YvQ0MuaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0NDLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQ0MgLS1taXNzaW5nLXNpdGUKCiMgRmxvcmlkYSBBdGxhbnRpYwp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0ZMQSAtLWtlZXAgZGF0YS9WQ0YvRkxBLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9GTEEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9GTEEgLS1taXNzaW5nLXNpdGUKCiMgRmxvcmlkYSBHdWxmIFNvdXRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvRkxHUyAtLWtlZXAgZGF0YS9WQ0YvRkxHUy5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvRkxHUy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0ZMR1MgLS1taXNzaW5nLXNpdGUKCiMgRmxvcmlkYSBHdWxmIE5vcnRoIAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0ZMR04gLS1rZWVwIGRhdGEvVkNGL0ZMR04uaW5kICAtLXJlY29kZSAtLXJlY29kZS1JTkZPLWFsbAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0ZMR04ucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9GTEdOIC0tbWlzc2luZy1zaXRlCgojIExvdWlzaWFuYQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTIucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0xBIC0ta2VlcCBkYXRhL1ZDRi9MQS5pbmQgIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvTEEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9MQSAtLW1pc3Npbmctc2l0ZQoKIyBNaXNzaXNzaXBwaSBTb3VuZCAKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEyLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvdGVtcC9NSVNTIC0ta2VlcCBkYXRhL1ZDRi9NSVNTLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9NSVNTLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvTUlTUyAtLW1pc3Npbmctc2l0ZQoKIyBNb2JpbGUgQmF5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvTUIgLS1rZWVwIGRhdGEvVkNGL01CLmluZCAgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9NQi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL01CIC0tbWlzc2luZy1zaXRlCgpgYGAKCkNvbXBhcmUgbWlzc2luZyBkYXRhIHBlciBzYW1wbGUgcmVnaW9uOgoKYGBge3IgY29tcGFyZSBtaXNzaW5nIGJ5IGxvY2F0LCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgcG9wcyB0byBsb29wIG92ZXIKcG9wIDwtIHVuaXF1ZShJbmRfUkFXJFBPUCkKCmxvY19taXNzaW5nIDwtIGxpc3QoKQoKIyBpbXBvcnQgbWlzc2luZyBkYXRhIHBlciBsb2N1cwpmb3IgKHAgaW4gcG9wKSB7CiAgCiAgbG9jX21pc3NpbmdbW3BdXSA8LSByZWFkX2RlbGltKHBhc3RlKCJkYXRhL1ZDRi8iLCBwLCAiLmxtaXNzIiwgc2VwID0gIiIpLCBkZWxpbSA9ICJcdCIpICU+JQogICAgc2VsZWN0KENIUiwgUE9TLCBGX01JU1MpICU+JQogICAgbXV0YXRlKFBPUCA9IHApCiAgCn0KCiMgY3JlYXRlIGRhdGEgZnJhbWUgd2l0aCBhbGwgaW5mb3JtYXRpb24KbG9jX21pc3NpbmcgPC0gbGRwbHkobG9jX21pc3NpbmcsIGRhdGEuZnJhbWUpCgpnZ3Bsb3QobG9jX21pc3NpbmcsIGFlcyh4ID0gRl9NSVNTKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gLjA1LCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC4xNSksCiAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWlzc2luZyBkYXRhIHBlciBsb2N1cyIpICsKICBzY2FsZV95X3NxcnQoKSArCiAgZmFjZXRfZ3JpZChQT1AgfiAuKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKaWRlbnRpZnkgbG9jaSB3aXRoIGhpZ2ggbWlzc2luZyBkYXRhIGluIGVhY2ggc2FtcGxlIGxvY2F0aW9uICg+IDE1ICUgbWlzc2luZyBkYXRhIGluIGEgZ2l2ZW4gbG9jYXRpb24pLgoKYGBge3J9CiMgaWRlbnRpZnkgbG9jaSB3aXRoIGhpZ2ggbWlzc2luZyBkYXRhIGluIGVhY2ggcmVnaW9uClNOUHMgPC0gZmlsdGVyKGxvY19taXNzaW5nLCBGX01JU1MgPiAwLjE1KSAKCmNvdW50KFNOUHMsIFBPUCkKCmNvbnRpZ3MgPC0gU05QcyAlPiUKICBkaXN0aW5jdChDSFIpCgpTTlBzIDwtIFNOUHMgJT4lCiAgc2VsZWN0KENIUiwgUE9TKQoKIyBXcml0ZSBjb250aWcvcG9zaXRpb24gdG8gdGV4dCBmaWxlLCB1c2UgZmlsZSB3aXRoIHZjZnRvb2xzIHRvIHJlbW92ZSBwb3NpdGlvbnMgZnJvbSBkYXRhc2V0IAp3cml0ZS50YWJsZShTTlBzLCBmaWxlID0gImRhdGEvVkNGL0xRX0YxMy5sb2NpIiwgCiAgICAgICAgICAgIGNvbC5uYW1lcz0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQpgYGAKClJlbW92ZSBsb2NpIGZyb20gZGF0YSBzZXQ6CgpgYGB7YmFzaH0KCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMi5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL3RlbXAvQk1BLkYxMyAtLWV4Y2x1ZGUtcG9zaXRpb25zIGRhdGEvVkNGL0xRX0YxMy5sb2NpIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEzIC0tc2l0ZS1xdWFsaXR5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEzIC0tc2l0ZS1tZWFuLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1taXNzaW5nLWluZHYKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEuRjEzLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLkYxMyAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuRjEzIC0taGV0CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1nZW5vLWRlcHRoCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1zaW5nbGV0b25zCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1pbmR2LWZyZXEtYnVyZGVuCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLkYxMy5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5GMTMgLS1mcmVxCgpgYGAKCkNvbXBhcmUgc3RhdHM6CgpgYGB7ciBzdGF0cyBGMTMsIGZpZy5oZWlnaHQ9MjAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19GMTMgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5GMTMiKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiU1AiLCAiTElCIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFLCBleHRyYSA9ICJtZXJnZSIpCgpsb2Nfc3RhdHNfRjEzIDwtIHJlYWQubG9jLnN0YXRzKGRpciA9ICJkYXRhL1ZDRiIsIHZjZiA9ICJCTUEuRjEzIikKCiMgcGxvdCBtaXNzaW5nIGRhdGEgcGVyIGluZHYgLS0tLQpwMSA8LSBnZ3Bsb3QoaW5kX3N0YXRzX0YxMywgYWVzKHggPSBNSVNTX0JNQS5GMTMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMDEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC4yNSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtaXNzaW5nIGRhdGEgcGVyIGluZHYiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCByZWFkIGRlcHRoIHBlciBpbmR2IC0tLS0KcDIgPC0gZ2dwbG90KGluZF9zdGF0c19GMTMsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjEzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGVwdGggdnMgbWlzc2luZyAtLS0tCnAzIDwtIGdncGxvdChpbmRfc3RhdHNfRjEzLCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLkYxMywgeSA9IE1JU1NfQk1BLkYxMykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMTMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDAuMjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBGaXMgcGVyIGluZHYgLS0tLQpwNCA8LSBnZ3Bsb3QoaW5kX3N0YXRzX0YxMywgYWVzKHggPSBGaXNfQk1BLkYxMykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQS5GMTMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiRmlzIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgRmlzIHZzIG1pc3NpbmcgZGF0YSBwZXIgaW5kdiAtLS0tCnA1IDwtIGdncGxvdChpbmRfc3RhdHNfRjEzLCBhZXMoeCA9IEZpc19CTUEuRjEzLCB5ID0gTUlTU19CTUEuRjEzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQS5GMTMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5GMTMsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDAuMjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiRmlzIHBlciBpbmR2IiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IEZpcyB2cyBtZWFuIGRlcHRoIHBlciBpbmR2IC0tLS0KcDYgPC0gZ2dwbG90KGluZF9zdGF0c19GMTMsIGFlcyh4ID0gRmlzX0JNQS5GMTMsIHkgPSBNRUFOX0RFUFRIX0JNQS5GMTMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihGaXNfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiRmlzIHBlciBpbmR2IiwgeSA9ICJtZWFuIGRlcHRoIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgoKIyBwbG90IGRpc3RyaWJ1dGlvbiBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIC0tLS0KcDcgPC0gZ2dwbG90KGxvY19zdGF0c19GMTMsIGFlcyh4ID0gTUlTU19CTUEuRjEzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuRjEzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiJSBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGlzdHJpYnV0aW9uIG1lYW4gcmVhZCBkZXB0aCAtLS0tCnA4IDwtIGdncGxvdChsb2Nfc3RhdHNfRjEzLCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLkYxMykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggdnMgbWlzc2luZyBkYXRhIC0tLS0KcDkgPC0gZ2dwbG90KGxvY19zdGF0c19GMTMsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuRjEzLCB5ID0gTUlTU19CTUEuRjEzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuRjEzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLkYxMywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMC4xKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gZGVwdGggcGVyIGxvY3VzIiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IGRlcHRoIHZzIFNOUCBxdWFsaXR5IC0tLS0Kc2l0ZV9xdWFsIDwtIHJlYWQudGFibGUoImRhdGEvVkNGL0JNQS5GMTMubHF1YWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBtdXRhdGUoUFJPQiA9IDEwXigtUVVBTC8xMCkpCgp0ZW1wIDwtIGRhdGEuZnJhbWUobG9jX3N0YXRzX0YxMyRNRUFOX0RFUFRIX0JNQS5GMTMsIHNpdGVfcXVhbCRRVUFMKSAlPiUKICByZW5hbWUoZGVwdGggPSBsb2Nfc3RhdHNfRjEzLk1FQU5fREVQVEhfQk1BLkYxMywgcXVhbCA9IHNpdGVfcXVhbC5RVUFMKQoKcDEwIDwtIGdncGxvdCh0ZW1wLCBhZXMoeCA9IGRlcHRoLCB5ID0gcXVhbCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oZGVwdGgsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4ocXVhbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiBkZXB0aCBwZXIgbG9jdXMiLCB5ID0gIlNOUCBxdWFsaXR5IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgbnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyB2cy4gbWVhbiBkZXB0aCAtLS0tCnRlbXAgPC0gbG9jX3N0YXRzX0YxMyAlPiUKICBjb3VudChDSFIpCgpwMTEgPC0gbGVmdF9qb2luKHRlbXAsIGxvY19zdGF0c19GMTMpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gbiwgeSA9IE1FQU5fREVQVEhfQk1BLkYxMykpICsKICBsYWJzKHggPSAibnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyIsIHkgPSAibWVhbiBkZXB0aCIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IG5vIG9mIFNOUHMgcGVyIGxvY3VzIC0tLS0KcDEyIDwtIGxvY19zdGF0c19GMTMgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGxhYnMoeCA9ICJudW1iZXIgb2YgU05QcyBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCm0xNSA8LSBtdWx0aXBsb3QocDEsIHAyLCBwMywgcDQsIHA1LCBwNiwgcDcsIHA4LCBwOSwgcDEwLCBwMTEsIHAxMiwgY29scz0yKQoKYGBgCgpDb21wYXJlIG51bWJlciBvZiBjb250aWdzIHZzIG51bWJlciBvZiBTTlBzLgoKYGBge3J9CgojIG51bWJlciBvZiBTTlBzCm5yb3cobG9jX3N0YXRzX0YxMykKCiMgbnVtYmVyIG9mIGNvbnRpZ3MgaW4gZGF0YSBzZXQKY29udGlncyA8LSBsb2Nfc3RhdHNfRjEzICU+JQogIGRpc3RpbmN0KENIUikKCm5yb3coY29udGlncykKCmBgYAoKTWVhbiBudW1iZXIgb2YgU05QcyBwZXIgY29udGlnIGlzIGByIG5yb3cobG9jX3N0YXRzX0YxMykvbnJvdyhjb250aWdzKWAuCgpgYGB7cn0KCmlzdGF0cyA8LSBsZWZ0X2pvaW4oaW5kX3N0YXRzX3JhdywgaW5kX3N0YXRzX0YxMykKCmBgYAoKCiMjIEZpbmFsIHRocmVzaG9sZHMgdmFsdWVzIGZvciBmaWx0ZXJlZCBkYXRhIHNldCBCTUE6CgoqIG1pbmltdW0gc2VxdWVuY2UgcXVhbGl0eSAobWluUSk6IDIwCiogbWluaW11bSBnZW5vdHlwZSBxdWFsaXR5IChtaW5HUSk6IDIwCiogbWluaW11bSBnZW5vdHlwZSBjYWxsIHJhdGUgcGVyIGxvY3VzIChnZW5vKTogOTAlCiogbWluaW11bSBnZW5vdHlwZSBkZXB0aCAobWluRCk6IDUKKiBtYXhpbXVtIG1pc3NpbmcgZGF0YSBwZXIgaW5kaXZpZHVhbCAobWlzc0luZCk6IDI1JQoqIG1lYW4gbWluaW11bSBkZXB0aCBwZXIgbG9jdXMgKG0tbWluRCk6IDE1CiogbWVhbiBtYXhpbXVtIGRlcHRoIChtLW1pbkQpOiAzMDAKKiBkRG9jZW50IGZpbHRlcnMgcnVuIGZvciBhbGxlbGljIGJhbGFuY2UsIG1hcHBpbmcgcXVhbGl0eSwgc3RyYW5kZWRuZXNzIGFuZCBwYWlyZWQgc3RhdHVzLCBkZXB0aC9xdWFsaXR5IHJhdGlvCiogSW5kZWxzIHJlbW92ZWQgZnJvbSBkYXRhIHNldAoqIG1pbmltdW0gZ2Vub3R5cGUgY2FsbCByYXRlIGJ5IHBvcHVsYXRpb246IDg1JQoKRGF0YSBzZXQgY29udGFpbnMgYHIgbnJvdyhsb2Nfc3RhdHNfRjEzKWAgU05QIHNpdGVzIG9uIGByIG5yb3coY29udGlncylgIGFuZCBgciBucm93KGluZF9zdGF0c19GMTMpYCBpbmRpdmlkdWFscy4KCiMgSGFwbG90eXBpbmcKCiMjIFByZXAgZm9yIGhhcGxvdHlwaW5nCgpDcmVhdGUgbGlzdCBvZiBpbmRpdmlkdWFscyByZXRhaW5lZCBpbiBmaW5hbCB2Y2YgZmlsZToKCkNoYW5nZSBzbyB0aGF0IG5ldyBmaWxlIGlzIHByaW50ZWQgaW50byBIYXBsb3R5cGluZy90ZW1wIGZvbGRlcgoKYGBge2Jhc2h9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BIC0tcmVjb2RlIC0tcmVjb2RlLUlORk8tYWxsCgp2Y2ZzYW1wbGVuYW1lcyBkYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BLnJlY29kZS52Y2YgPiBkYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BLmluZGl2aWR1YWxzCgpgYGAKClVzZSBgQk1BLUJNQS5pbmRpdmlkdWFsc2AgdG8gY3JlYXRlIGBwb3BtYXBgIGFzIGEgdGFiLXNlcGFyYXRlZCBmaWxlIG9mIGluZGl2aWR1YWxzIGFuZCB0aGVpciBwb3B1bGF0aW9uIGRlc2lnbmF0aW9uLCB3aXRoIG9uZSBpbmRpdmlkdWFsIHBlciBsaW5lIChtYWtlIHN1cmUgVU5JWCBmb3JtYXQpLiBUaGlzIGZpbGUgaXMgbmVlZGVkIHRvIHdyaXRlIHRoZSBnZW5lcG9wIGZpbGUsIGlmIG5vdCBwcm92aWRlZCB0aGUgc2NyaXB0IHdpbGwgcnVuIHRocm91Z2ggdGhlIHByb2Nlc3MgYnV0IG5vdCB3cml0ZSBhIGdlbmVwb3AgZmlsZSBhbmQgcGxhY2UgaW50byBzYW1lIGZvbGRlciBgcmFkX2hhcGxvdHlwZXIucGxgIHdpbGwgYmUgcnVuIGZyb20uCgpgYGB7cn0KCnBvcG1hcCA8LSByZWFkLnRhYmxlKCJkYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BLmluZGl2aWR1YWxzIiwgCiAgICAgICAgICAgICAgICAgICAgIGNvbC5uYW1lcyA9ICJJTkRWIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiUE9QIiwgIkxJQiIsICJJRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFLCBleHRyYSA9ICJtZXJnZSIpICU+JQogIHNlbGVjdChJTkRWLCBQT1ApCgp3cml0ZS50YWJsZShwb3BtYXAsICJkYXRhL0hhcGxvdHlwaW5nL3RlbXAvcG9wbWFwIiwgCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCmBgYAoKUGxhY2UgYWxsIG5lY2Vzc2FyeSBmaWxlcyBpbiBgZGF0YS9IYXBsb3R5cGluZy90ZW1wYCBkaXJlY3RvcnkgKGJhbSwgZmFzdHEsIHJlZmVyZW5jZS5mYXN0YSwgdmNmLWZpbGUpCgpgYGB7YmFzaCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL1NFUS9CTUEtMS8qLmZxLmd6IC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL0hhcGxvdHlwaW5nL3RlbXAKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvU0VRL0JNQS0xLyouYmFtKiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL1NFUS9CTUEtMi8qLmZxLmd6IC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL0hhcGxvdHlwaW5nL3RlbXAKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvU0VRL0JNQS0yLyouYmFtKiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wCmxuIC1zIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL1NFUS9CTUEtMy8qLmZxLmd6IC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL0hhcGxvdHlwaW5nL3RlbXAKbG4gLXMgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvU0VRL0JNQS0zLyouYmFtKiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wCgpgYGAKCiMjIFJ1biBIYXBsb3R5cGVyCgpgYGB7YmFzaCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCiMgZGlmZmljdWx0eSBydW5uaW5nIGZyb20gUgpyYWRfaGFwbG90eXBlci5wbCAtdiBCTUEucmVjb2RlLnZjZiAtciByZWZlcmVuY2UuZmFzdGEgLXggMzUgLWQgMTAgLXogMyAtbSAuMjUgLWcgQk1BLmdlbiAtcCBwb3BtYXAKCmBgYAoKQ29weSBmaWxlcyBmb3IgYW5hbHlzaXMgaW50byBgZGF0YS9IYXBsb3R5cGluZy9gLWZvbGRlcgoKYGBge2Jhc2h9CgpjZCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wCnJtICouZnEuZ3oKcm0gKi5iYW0qCgpjcCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wL2luZF9zdGF0cy5vdXQgL2hvbWUvc29sZWFyeS9HQUZGVE9QUy9CTUFfUE9QR0VOL2RhdGEvSGFwbG90eXBpbmcvCgpjcCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy90ZW1wL3N0YXRzLm91dCAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy8KCmNwIC9ob21lL3NvbGVhcnkvR0FGRlRPUFMvQk1BX1BPUEdFTi9kYXRhL0hhcGxvdHlwaW5nL3RlbXAvQk1BLmdlbiAvaG9tZS9zb2xlYXJ5L0dBRkZUT1BTL0JNQV9QT1BHRU4vZGF0YS9IYXBsb3R5cGluZy8KCmBgYAoKIyBIYXBsb3R5cGUgZmlsdGVyaW5nCgojIyBPdmVydmlldyBvZiBoYXBsb3R5cGluZyBzdWNjZXNzCgpDb21wYXJpc29uIG9mIHRoZSBudW1iZXIgb2YgbG9jaSB0aGF0IHdlcmUgZmlsdGVyZWQgZHVlIHRvIGV4Y2VzcyBudW1iZXIgb2YgbWlzc2luZyBkYXRhIG9yIHN1c3BlY3RlZCBwYXJhbG9ncyBkdXJpbmcgdGhlIGhhcGxvdHlwaW5nIHByb2Nlc3MgdG8gdGhvc2UgdGhhdCBwYXNzZWQuIEhhcGxvdHllciB3YXMgcnVuIHdpdGhvdXQgYW55IHRocmVzaG9sZCB2YWx1ZXMgKG90aGVyIHRoYW4gZGVmYXVsdCB2YWx1ZXMpLiBUaGUgZ2VuZXBvcCBmaWxlIG9ubHkgY29udGFpbnMgbG9jaSB0aGF0IHBhc3NlZCBoYXBsb3R5cGluZyBzdGFnZS4KCmBgYHtyIGltcG9ydCBzdGF0cy5vdXQgZmlsZSwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgaW1wb3J0IHN0YXRzIGZpbGVzIGdlbmVyYXRlZCBieSBoYXBsb3R5cGVyCmhhcF9zdGF0cyA8LSByZWFkLmhhcC5zdGF0cygiZGF0YS9IYXBsb3R5cGluZy9zdGF0cy5vdXQiKQoKCgpoYXBfaW5kX3N0YXRzIDwtIHJlYWQuZGVsaW0oImRhdGEvSGFwbG90eXBpbmcvaW5kX3N0YXRzLm91dCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCnRlbXAgPC0gaGFwX2luZF9zdGF0cyAlPiUKICByZW5hbWUoSU5EViA9IEluZCkKCmlzdGF0cyA8LSBsZWZ0X2pvaW4oaXN0YXRzLCB0ZW1wKQoKIyB2aWV3IGNvbXBhcmlzb24gb2YgZmlsdGVyZWQgdnMuIHBhc3NlZCBsb2NpCnBsb3QuZmlsdGVyLnN0YXR1cyhoYXBfc3RhdHMpCgpgYGAKClJlbW92ZSBmaWx0ZXJlZCBsb2NpIGZyb20gZGF0YSBzZXQuCgpgYGB7cn0KCmNvdW50KGhhcF9zdGF0cywgU3RhdHVzID09ICJGSUxURVJFRCIpCgpoYXBfc3RhdHMgPC0gcmVtb3ZlLmZpbHRlcmVkLmhhcHMoaGFwX3N0YXRzKQoKYGBgCgpgciBucm93KGhhcF9zdGF0cylgIGxvY2kgcGFzc2VkIGhhcGxvdHlwaW5nIHByb2Nlc3MuCgpgYGB7ciBwbG90IHN0YXRzLm91dCBmaWxlLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD05LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcGxvdC5oYXAuc3RhdHMoaGFwX3N0YXRzKQoKYGBgCgpEYXRhIHNldCBjb250YWlucyBgciBucm93KGhhcF9pbmRfc3RhdHMpYCBpbmRpdmlkdWFsczoKCmBgYHtyIHBsb3QgaW5kLnN0YXRzLm91dCBmaWxlLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD05LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcGxvdC5pbmQuaGFwLnN0YXRzKGhhcF9pbmRfc3RhdHMpCgpgYGAKCiMjIElkZW50aWZ5IHRocmVzaG9sZCB2YWx1ZXMgdG8gZmlsdGVyIGRhdGEgc2V0CgojIyMgUHJvcG9ydGlvbiBvZiBpbmRpdmlkdWFscyBoYXBsb3R5cGVkCgpgYGB7ciBwcm9wIGluZHYgaGFwbG90eXBlZCwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGhhcF9zdGF0cyA8LSByZWFkLmhhcC5zdGF0cygiZGF0YS9IYXBsb3R5cGluZy9zdGF0cy5vdXQiKQoKcDEgPC0gZ2dwbG90KGhhcF9zdGF0cywgYWVzKHggPSBQcm9wX0hhcGxvdHlwZWQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAyNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oUHJvcF9IYXBsb3R5cGVkLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC45KSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gInByb3BvcnRpb24gaW5kaXZpZHVhbHMgaGFwbG90eXBlZCIpICsKICB0aGVtZV9zdGFuZGFyZAoKcDIgPC0gZ2dwbG90KGhhcF9zdGF0cywgYWVzKHggPSBQcm9wX0hhcGxvdHlwZWQsIHkgPSBQb3NzX1BhcmFsb2cpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihQcm9wX0hhcGxvdHlwZWQsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJwcm9wb3J0aW9uIGluZGl2aWR1YWxzIGhhcGxvdHlwZWQiLCB5ID0gInBvc3NpYmxlIHBhcmFsb2dzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMyA8LSBnZ3Bsb3QoaGFwX3N0YXRzLCBhZXMoeCA9IFByb3BfSGFwbG90eXBlZCwgeSA9IGBMb3dfQ292Lkdlbm9fRXJyYCkpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKFByb3BfSGFwbG90eXBlZCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gInByb3BvcnRpb24gaW5kaXZpZHVhbHMgaGFwbG90eXBlZCIsIHkgPSAibG93IGNvdmVyYWdlIGVycm9yIikgKwogIHRoZW1lX3N0YW5kYXJkCgptdWx0aXBsb3QocDEsIHAyLCBwMywgY29scyA9IDMpCgpgYGAKCkZsYWcgbG9jaSBzdWNjZXNzZnVsbHkgaGFwbG90eXBlZCBpbiA8IDkwJSBvZiBpbmRpdmlkdWFscy4KCmBgYHtyIGZpbHRlciBsb2NpIGdlbm90eXBlIGNhbGwgcmF0ZSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbnVtYmVyIG9mIGxvY2kgY2FsbGVkIGluID45NSUgaW5kaXZpZHVhbHMKY291bnQoaGFwX3N0YXRzLCBQcm9wX0hhcGxvdHlwZWQgPCAwLjkpCgojIGNyZWF0ZSB2ZWN0b3Igb2YgbG9jaSB0byByZW1vdmUgKGNob29zZSBjdXQtb2ZmKQpQcm9wX0hhcGxvdHlwZWQgPC0gZmlsdGVyLmxvY2kucHJvcF9oYXBsb3R5cGVkKGhhcF9zdGF0cywgMC45KQoKYGBgCgpgciBsZW5ndGgoUHJvcF9IYXBsb3R5cGVkKWAgbG9jaSB3ZXJlIGZsYWdnZWQgYXMgZ2Vub3R5cGUgY2FsbCByYXRlIDwgMC45LgoKIyMjIFBvc3NpYmxlIHBhcmFsb2dzIHBlciBsb2N1cwoKTG9jaSBhcmUgZmxhZ2dlZCBhcyBwb3NzaWJsZSBwYXJhbG9ncyBmb3IgYW4gaW5kaXZpZHVhbHMgd2hlbiBtb3JlIHRoYW4gdGhlIGV4cGVjdGVkIG51bWJlciBvZiBoYXBsb3R5cGVzIGJhc2VkIG9uIHRoZSBTTlAgZ2Vub3R5cGUgY2FsbCAoaG9tb3p5Z290ZSwgaGV0ZXJvenlnb3RlKSBhcmUgZGV0ZWN0ZWQuCgpgYGB7ciBwb3NzIHBhcmFsb2dzIHBlciBsb2N1cywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmdncGxvdChoYXBfc3RhdHMsIGFlcyh4ID0gUG9zc19QYXJhbG9nKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMiwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oUG9zc19QYXJhbG9nLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gKG5yb3coaGFwX2luZF9zdGF0cykqMC4wMSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAicG9zc2libGUgcGFyYWxvZ3MgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCjEgJSBvZiBpbmRpdmlkdWFsczogYHIgbnJvdyhoYXBfaW5kX3N0YXRzKSowLjAxYCAKNSAlIG9mIGluZGl2aWR1YWxzOiBgciBucm93KGhhcF9pbmRfc3RhdHMpKjAuMDVgIAoKRmxhZyBsb2NpIHRoYXQgYXJlIGZsYWdnZWQgYXMgcG90ZW50aWFsIHBhcmFsb2dzIGluIDUgb3IgbW9yZSBpbmRpdmlkdWFscy4KNApgYGB7ciBmaWx0ZXIgbG9jaSBwYXJhbG9nc30KCiMgbnVtYmVyIG9mIGxvY2kgd2l0aCBQb3NzX1BhcmFsb2dzCmNvdW50KGhhcF9zdGF0cywgUG9zc19QYXJhbG9nID4gNCkKCiMgY3JlYXRlIHZlY3RvciBvZiBsb2NpIHRvIHJlbW92ZSAoY2hvb3NlIGN1dC1vZmYpClBvc3NfUGFyYWxvZ3MgPC0gZmlsdGVyLmxvY2kucGFyYWxvZ3MoaGFwX3N0YXRzLCA0KQoKYGBgCgpgciBsZW5ndGgoUG9zc19QYXJhbG9ncylgIGxvY2kgd2VyZSBmbGFnZ2VkIGFzIHBvc3NpYmxlIHBhcmFsb2dzLgoKIyMjIE51bWJlciBvZiBTTlBzICYgSGFwbG90eXBlcyBwZXIgbG9jdXMKCkVhY2ggbG9jdXMgdmFyaWVzIGluIHRoZSBudW1iZXIgb2YgU05QcyBkZXRlY3RlZCB3aGljaCBkZXRlcm1pbmVzIHRoZSBudW1iZXIgb2YgaGFwbG90eXBlcyBleHBlY3RlZCBpbiB0aGF0IHBvcHVsYXRpb24uIAoKYGBge3Igbm8gU05QcywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmdncGxvdChoYXBfc3RhdHMsIGFlcyh4ID0gU2l0ZXMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihTaXRlcywgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDI1KSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm51bWJlciBvZiBTTlBzIHBlciBjb250aWciKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKRmlsdGVyaW5nIGxvY2kgYmFzZWQgb24gbnVtYmVyIG9mIFNOUHMgY29udGFpbmVkIG9uIHRoYXQgbG9jdXMgY291bGQgYmlhcyB0aGUgZGF0YSBzZXQgYXMgbG9jaSB3aXRoIGhpZ2ggcmVjb21iaW5hdGlvbiBtYXkgYmUgcmVtb3ZlZC4gT24gdGhlIG90aGVyIGhhbmQsIGFzc3VtaW5nIGFuIGFwcHJveGltYXRlIGxlbmd0aCBvZiAyNTAgYnAgbG9jaSB3aXRoIG1vcmUgdGhhbiBgciAyNTAqMC4xYCBTTlBzIHdvdWxkIG1lYW4gdGhhdCAxMCUgb2YgYmFzZXMgYXJlIGEgcG9seW1vcnBoaXNtcy4KCmBgYHtyIHNpdGVzIHZzIHBhcmFsb2dzLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD04fQoKcDEgPC0gZ2dwbG90KGhhcF9zdGF0cywgYWVzKHggPSBIYXBsb3R5cGVzLCB5ID0gUG9zc19QYXJhbG9nKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIGxhYnMoeCA9ICJuby4gaGFwbG90eXBlcyIsIHkgPSAicG9zc2libGUgcGFyYWxvZ3MiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnAyIDwtIGdncGxvdChoYXBfc3RhdHMsIGFlcyh4ID0gU2l0ZXMsIHkgPSBQb3NzX1BhcmFsb2cpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgbGFicyh4ID0gIm5vLiBvZiBzaXRlcyIsIHkgPSAiICIpICsKICB0aGVtZV9zdGFuZGFyZAogIAptdWx0aXBsb3QocDEsIHAyLCBjb2xzID0gMikKCmBgYAoKSWRlbnRpZnkgbnVtYmVyIG9mIGhhcGxvdHlwZXMgbG9jaSB3aXRoID4gMzUgU05QIHNpdGVzLgoKYGBge3IgZmlsdGVyIG5vIG9mIFNOUHN9Cgpjb3VudChoYXBfc3RhdHMsIFNpdGVzID4gMzUpCgpOb1NOcHMgPC0gZmlsdGVyLmxvY2kubm9TTlBzKGhhcF9zdGF0cywgMzUpCgpgYGAKCmByIGxlbmd0aChOb1NOcHMpYCBsb2NpIHdlcmUgZmxhZ2dlZC4KCkFzc3VtaW5nIHRoYXQgbXV0YXRpb24gaXMgdGhlIG9ubHkgbWVjaGFuaXNtIHJlc3VsdGluZyBpbiBuZXcgaGFwbG90eXBlcywgdGhlIG1heGltdW0gZXhwZWN0ZWQgbnVtYmVyIG9mIGhhcGxvdHlwZXMgcGVyIGxvY3VzIGlzIG51bWJlciBvZiBTTlBzIE4gKyAxLgoKYGBge3IgeHRyYSBoYXBsb3R5cGVzLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpwMSA8LSBnZ3Bsb3QoaGFwX3N0YXRzLCBhZXMoeCA9IEhhcGxvdHlwZXMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihIYXBsb3R5cGVzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gcXVhbnRpbGUoSGFwbG90eXBlcywgLjk5LCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiIyBoYXBsb3R5cGVzIHBlciBsb2N1cyIsIHkgPSAiIyBsb2NpIikgKwogIHRoZW1lX3N0YW5kYXJkCgp0ZW1wIDwtIGhhcF9zdGF0cyAlPiUKICBzZWxlY3QoTG9jdXMsIFNpdGVzLCBIYXBsb3R5cGVzLCBQcm9wX0hhcGxvdHlwZWQsIExvd19Db3YuR2Vub19FcnIsIFBvc3NfUGFyYWxvZykgJT4lCiAgbXV0YXRlKGV4cF9zaXRlcyA9IFNpdGVzICsgMSkgJT4lCiAgbXV0YXRlKHh0cmEgPSBIYXBsb3R5cGVzIC0gU2l0ZXMpCgpwMiA8LSBnZ3Bsb3QodGVtcCwgYWVzKHggPSBTaXRlcywgeSA9IFBvc3NfUGFyYWxvZykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIjIFNOUCBzaXRlcyBwZXIgbG9jdXMiLCB5ID0gInBvc3NpYmxlIHBhcmFsb2dzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwMyA8LSBnZ3Bsb3QodGVtcCwgYWVzKHggPSBTaXRlcywgeSA9IHh0cmEpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxMCwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDI1LCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIiMgU05QIHNpdGVzIHBlciBsb2N1cyIsIHkgPSAiIyBleHRyYSBoYXBsb3R5cGVzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwNCA8LSBnZ3Bsb3QodGVtcCwgYWVzKHggPSB4dHJhLCB5ID0gUHJvcF9IYXBsb3R5cGVkKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjksIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIjIGV4dHJhIGhhcGxvdHlwZXMiLCB5ID0gInByb3BvcnRpb24gb2YgaW5kdiBoYXBsb3R5cGVkIikgKwogIHRoZW1lX3N0YW5kYXJkCgpwNSA8LSBnZ3Bsb3QodGVtcCwgYWVzKHggPSB4dHJhLCB5ID0gTG93X0Nvdi5HZW5vX0VycikpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDI1LCBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIiMgZXh0cmEgaGFwbG90eXBlcyIsIHkgPSAicG90ZW50aWFsIGdlbm90eXBpbmcgZXJyb3IiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnA2IDwtIGdncGxvdCh0ZW1wLCBhZXMoeCA9IHh0cmEsIHkgPSBQb3NzX1BhcmFsb2cpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUsIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyNSwgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIjIGV4dHJhIGhhcGxvdHlwZXMiLCB5ID0gInBvc3NpYmxlIHBhcmFsb2dzIikgKwogIHRoZW1lX3N0YW5kYXJkCgptMjEgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIGNvbHMgPSAyKQoKYGBgCgpBZ2FpbiwgcmVtb3ZpbmcgbG9jaSB3aXRoIHVuZXhwZWN0ZWRseSBoaWdoIG51bWJlcnMgb2YgaGFwbG90eXBlcyBtYXkgYmlhcyB0aGUgZGF0YSBzZXQsIGFzIGxvY2kgd2l0aCBlLmcuIGhpZ2ggcmVjb21iaW5hdGlvbiBtYXkgYmUgcmVtb3ZlZCBmcm9tIHRoZSBkYXRhIHNldC4KCmBgYHtyIGZpbHRlciBubyBvZiBoYXBsb3R5cGVzfQoKY291bnQodGVtcCwgeHRyYSA+PSA1MCkKCiMgY3JlYXRlIHZlY3RvciBvZiBsb2NpIHRvIHJlbW92ZQpOb0hhcHMgPC0gZmlsdGVyKHRlbXAsIHh0cmEgPj0gNTApIAoKTm9IYXBzIDwtIE5vSGFwcyRMb2N1cwoKYGBgCgpgciBsZW5ndGgoTm9IYXBzKWAgbG9jaSB3ZXJlIGZsYWdnZWQgZm9yIGV4Y2Vzc2l2ZSBudW1iZXIgb2YgaGFwbG90eXBlcyBjb21wYXJlZCB0byB0aGUgbnVtYmVyIG9mIFNOUHMgYXQgdGhhdCBsb2N1cy4KCiMjIyBMb3cgQ292ZXJhZ2UvR2Vub3R5cGluZyBFcnJvcgoKQWZ0ZXIgY29tYmluaW5nIFNOUHMgb24gdGhlIHNhbWUgY29udGlnIGR1cmluZyB0aGUgaGFwbG90eXBpbmcgcHJvY2VzcywgaXQgaXMgcG9zc2libGUgdG8gb2JzZXJ2ZSBmZXdlciB0aGFuIHRoZSBleHBlY3RlZCBudW1iZXIgb2YgaGFwbG90eXBlcyBiYXNlZCBvbiB0aGUgZ2Vub3R5cGUgY2FsbCAoaGV0ZXJvenlnb3RlL2hvbW96eWdvdGUpLiBXaGVuIHRoaXMgb2NjdXJzLCB0aGF0IGdlbm90eXBlIGlzIGNvZGVkIGFzIG1pc3NpbmcuIEZvciBlYWNoIGxvY3VzIHRoZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMgZm9yIHdoaWNoIGlzIGl0IGZsYWdnZWQgYXMgYSBwb3RlbnRpYWwgYSBwb3RlbnRpYWwgZ2Vub3R5cGluZyBlcnJvciBvciBzdWZmZXJpbmcgZnJvbSBudWxsIGFsbGVsZXMgZHVlIHRvIGxvdyBjb3ZlcmFnZSBkZXRlY3RlZCBmb3IgYSBnaXZlbiBsb2N1cyBpcyByZWNvcmRlZC4gCgpgYGB7ciBsb3cgY292IGdlbm90eXBnIGVycm9yLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKZ2dwbG90KGhhcF9zdGF0cywgYWVzKHggPSBMb3dfQ292Lkdlbm9fRXJyKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTG93X0Nvdi5HZW5vX0VyciwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IChucm93KGhhcF9pbmRfc3RhdHMpKjAuMDUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gInBvdGVudGlhbCBnZW5vdHlwaW5nIGVycm9yIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCkxvY2kgd2l0aCBwcm9ub3VuY2VkIHBhdHRlcm5zIG9mIGdlbm90eXBpbmcgZXJyb3IgbGlrZWx5IGR1ZSB0byBsb3cgY292ZXJhZ2Ugd2lsbCBoYXZlIGxvdyBzdWNjZXNzIHJhdGUgZm9yIGdlbm90eXBpbmcsIGkuZS4gdGhleSB3aWxsIGJlIGNhdWdodCBpbiBtaXNzaW5nIGRhdGEgZmlsdGVycy4gQ292ZXJhZ2UgaXNzdWVzIGFyZSBsaWtlbHkgZ2Vub3R5cGUgc3BlY2ZpYzsgcHJldmlvdXMgZmlsdGVycyBoYXZlIHRhcmdldGVkIGxvY2kgYW5kIGluZGl2aWR1YWxzIHdpdGggaGlnaCB2YXJpYW5jZSBpbiBjb3ZlcmFnZSBhbmQgc3VzcGVjdCBnZW5vdHBlcyBoYXZlIGJlZW4gY29kZWQgYXMgbWlzc2luZywgaS5lLiB0aGlzIGZpbHRlciBuZWVkIG5vdCBiZSB2ZXJ5IGNvbnNlcnZhdGl2ZSwgcmVnYXJkbGVzcywgbG9jaSB0aGF0IGFyZSByZXBlYXRlZGx5IGJlaW5nIGZsYWdnZWQgYXMgcHJvYmxlbWF0aWMgc2hvdWxkIGJlIHJlbW92ZWQuCgpgYGB7ciBmaWx0ZXIgbG93IGNvdmVyYWdlL2dlbm90eXBpbmcgZXJyb3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIHN1bW1hcnkgb2YgY291bnQgb2YgcG9zc2libGUgZ2Vub3R5cGluZyBlcnJvcnMKY291bnQoaGFwX3N0YXRzLCBMb3dfQ292Lkdlbm9fRXJyID4gMTApCgojIGNyZWF0ZSB2ZWN0b3Igb2YgbG9jaSB0byByZW1vdmUKR2Vub19FcnIgPC0gZmlsdGVyLmxvY2kuZ2Vub19lcnIoaGFwX3N0YXRzLCAxMCkKCmBgYAoKYHIgbGVuZ3RoKEdlbm9fRXJyKWAgbG9jaSB3ZXJlIGZsYWdnZWQgYXMgcG90ZW50aWFsbHkgYWZmZWN0ZWQgYnkgZ2Vub3R5cGluZyBlcnJvci4KCiMjIyBGbGFnIHByb2JsZW1hdGljIGluZGl2aWR1YWxzCgpMb2NpIHRoYXQgYXJlIG5vdCBzdWNjZXNzZnVsbHkgaGFwbG90eXBlZCBpbiBhbiBpbmRpdmlkdWFsIGR1ZSB0byBtaXNzaW5nIGRhdGEsIGNvbXBsZXggbG9jdXMsIGhhcGxvdHlwZWQgZ2Vub3R5cGUgaXMgaGlnaGVyL2xvd2VyIHRoYW4gU05QIGhhcGxvdHlwZSBpbiBhIGdpdmVuIGluZGl2aWR1YWwgYXJlIGNvZGVkIGFzIG1pc3NpbmcgZm9yIHRoYXQgaW5kaXZpZHVhbC4gUHJvYmxlbWF0aWMgaW5kaXZpZHVhbCBjYW4gYmUgaWRlbnRpZmllZCBhcyBoYXZpbmcgYSBoaWdoIHByb3BvcnRpb24gb2YgbWlzc2luZyBkYXRhLgoKKipJbmRpdmlkdWFscyB3aXRoIGxvdyBwcm9wb3J0aW9uIG9mIHN1Y2Nlc3NmdWxseSBoYXBsb3R5cGVkIGxvY2kqKgoKYGBge3IgbWlzc2luZyBpbmR2LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKZ2dwbG90KGhhcF9pbmRfc3RhdHMsIGFlcyh4ID0gUHJvcF9TdWNjZXNzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oUHJvcF9TdWNjZXNzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC43NSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJwcm9wb3J0aW9uIGxvY2kgc3VjY2Vzc2Z1bGx5IGhhcGxvdHlwZWQiKSArCiAgdGhlbWVfc3RhbmRhcmQKCmBgYAoKUHJvYmxlbSBpbmRpdmlkdWFscyBjYW4gYmUgaWRlbnRpZmllZCBieSBjaG9vc2luZyBhIGN1dC1vZmYgdmFsdWUgZm9yIHRoZSBtaW5pdW0gcHJvcG9ydGlvbiBvZiBzdWNlc3NmdWxseSBoYXBsb3R5cGVkIGxvY2kgYW5kIGV4Y2x1ZGluZyBpbmRpdmlkdWFscyBiZWxvdyB0aGF0IHRocmVzaG9sZCB2YWx1ZS4gUmVtb3ZpbmcgbG9jaSB3aXRoIGxvdyBoYXBsb3R5cGluZyBzdWNjZXNzIHdpdGggZGVjcmVhc2UgdGhlIGFtb3VudCBvZiBtaXNzaW5nIGRhdGEuIFRoZXJlZm9yZSwgZmluYWwgbWlzc2luZyBkYXRhIGN1dC1vZmZzIHNob3VsZCBiZSBhcHBsaWVkICphZnRlciogcmVtb3ZpbmcgdGhvc2UgbG9jaSBmcm9tIHRoZSBkYXRhIHNldCwgdGhvdWdoIGl0IGlzIGltcG9ydGFudCB0byBmbGFnIHBvdGVudGlhbGx5IHByb2JsZW1hdGljIGluZGl2aWR1YWxzIGJhc2VkIG9uIHRoZWlyIGhhcGxvdHlwaW5nIHN0YXRzIGF0IHRoaXMgcG9pbnQuCgpgYGB7ciBmaWx0ZXIgc3VjY2VzcyBoYXBsb3R5cGVkIGluZHZ9CgojIGNvdW50IGluZGl2aWR1YWxzIGFib3ZlIHNldCB0aHJlc2hvbGQKY291bnQoaGFwX2luZF9zdGF0cywgUHJvcF9TdWNjZXNzIDwgLjc1KQoKIyBjcmVhdGUgdmVjdG9yIG9mIGluZHYgdG8gcmVtb3ZlIChjaG9vc2UgY3V0LW9mZikKUHJvcFN1Y2Nlc3NJbmQgPC0gZmlsdGVyLmluZC5wcm9wX3N1Y2Nlc3MoaGFwX2luZF9zdGF0cywgLjc1KQoKd3JpdGUudGFibGUoUHJvcFN1Y2Nlc3NJbmQsICJkYXRhL1BPUEdFTi9wcm9wU3VjYy5pbmR2IiwgCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IFRSVUUsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiKQoKIyBWaWV3KGFzLmRhdGEuZnJhbWUoUHJvcFN1Y2Nlc3NJbmQpKQoKYGBgCgoqKlBvc3NpYmxlIHBhcmFsb2dzIHBlciBpbmRpdmlkdWFsKioKCkluZGl2aWR1YWxzIHdpdGggaGlnaCBwcm9wb3J0aW9uIG9mIGxvY2kgZmxhZ2dlZCBhcyBwb3NzaWJsZSBwYXJhbG9ncyBzaG91bGQgYmUgZmxhZ2dlZCBhcyBwb3RlbnRpYWwgcHJvYmxlbSBpbmRpdmlkdWFscy4gCgpgYGB7ciBwb3NzIHBhcmFsb2dzIHBlciBpbmR2LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKZ2dwbG90KGhhcF9pbmRfc3RhdHMsIGFlcyh4ID0gUG9zc19QYXJhbG9ncykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihQb3NzX1BhcmFsb2dzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gKG5yb3coaGFwX3N0YXRzKSowLjAxKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJubyBvZiBsb2NpIHBvdGVudGlhbCBwYXJhbG9ncyIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpDdXQtb2ZmIGZvciBpbmRpdmlkdWFscyB3aXRoIGxvY2kgZmxhZ2dlZCBwYXJhbG9ncyBpbiA+IDElIG9mIGxvY2kgaXMgYHIgbnJvdyhoYXBfc3RhdHMpKjAuMDFgLgoKYGBge3IgZmlsdGVyIHBhcmFsb2dzIGluZHZ9CgojIGNvdW50IGluZGl2aWR1YWxzIGFib3ZlIHNldCB0aHJlc2hvbGQKY291bnQoaGFwX2luZF9zdGF0cywgUG9zc19QYXJhbG9ncyA+IDEwMCkKCiMgY3JlYXRlIHZlY3RvciBvZiBpbmR2IHRvIHJlbW92ZSAoY2hvb3NlIGN1dC1vZmYpClBvc3NfUGFyYWxvZ0luZCA8LSBmaWx0ZXIuaW5kLnBhcmFsb2dzKGhhcF9pbmRfc3RhdHMsIDEwMCkKCndyaXRlLnRhYmxlKFBvc3NfUGFyYWxvZ0luZCwgImRhdGEvUE9QR0VOL3Bvc3NQYXJhbC5pbmR2IiwgCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IFRSVUUsIHJvdy5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiKQoKYGBgCgpUaGUgaGlnaGVzdCBudW1iZXIgb2YgZmxhZ2dlZCBsb2NpIGluIGFuIGluZGl2aWR1YWxzIGlzIGByIG1heChoYXBfaW5kX3N0YXRzJFBvc3NfUGFyYWxvZ3MsIG5hLnJtID0gVFJVRSlgLCB3aGljaCBpcyBlcXVpdmFsZW50IHRvIGByIHJvdW5kKG1heChoYXBfaW5kX3N0YXRzJFBvc3NfUGFyYWxvZ3MsIG5hLnJtID0gVFJVRSkvbnJvdyhoYXBfc3RhdHMpLCBkaWdpdHMgPSA0KSoxMDBgJSBvZiBsb2NpLgoKKipJbmRpdmlkdWFscyB3aXRoIGhpZ2ggcHJvcG9ydGlvbiBvZiBwb3RlbnRpYWwgYWxsZWxlIGRyb3BvdXQvZ2Vub3R5cGluZyBlcnJvcioqCgpgYGB7ciBnZW5vdHlwZyBlcnJvciBwZXIgaW5kdiwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmdncGxvdChoYXBfaW5kX3N0YXRzLCBhZXMoeCA9IExvd19Db3ZlcmFnZS5FcnJvcnMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihMb3dfQ292ZXJhZ2UuRXJyb3JzLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gKG5yb3coaGFwX3N0YXRzKSowLjAxKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICIjIGxvY2kgcG90ZW50aWFsIGdlbm90eXBpbmcgZXJyb3IiLCB5ID0gIiMgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpSZW1vdmUgaW5kaXZpZHVhbHMgd2l0aCBoaWdoIHByb3BvcnRpb24gb2YgbG9jaSB0aGF0IGhhdmUgYmVlbiBmbGFnZ2VkIGFzIHBvdGVudGlhbCBhbGxlbGUgZHJvcG91dHMvZ2Vub3R5cGluZyBlcnJvci4KCmBgYHtyIGZpbHRlciBnZW5vdHlwaW5nIGVycm9yIGluZHZ9CgojIGNvdW50IGluZGl2aWR1YWxzIGFib3ZlIHNldCB0aHJlc2hvbGQKY291bnQoaGFwX2luZF9zdGF0cywgTG93X0NvdmVyYWdlLkVycm9ycyA+IDI4NSkKCiMgY3JlYXRlIHZlY3RvciBvZiBpbmR2IHRvIHJlbW92ZSAoY2hvb3NlIGN1dC1vZmYpCkdlbm9FcnJJbmR2IDwtIGZpbHRlci5pbmQuZ2Vub19lcnIoaGFwX2luZF9zdGF0cywgMjg1KQoKd3JpdGUudGFibGUoR2Vub0VyckluZHYsICJkYXRhL1BPUEdFTi9HZW5vRXJyLmluZHYiLCAKICAgICAgICAgICAgY29sLm5hbWVzID0gVFJVRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UsIHNlcCA9ICJcdCIpCgojIFZpZXcoR2Vub0VyckluZHYpCgpgYGAKClRoZSBoaWdoZXN0IG51bWJlciBvZiBmbGFnZ2VkIGxvY2kgaW4gYW4gaW5kaXZpZHVhbHMgaXMgYHIgbWF4KGhhcF9pbmRfc3RhdHMkTG93X0NvdmVyYWdlLkVycm9ycywgbmEucm0gPSBUUlVFKWAsIHdoaWNoIGlzIGVxdWl2YWxlbnQgdG8gYHIgcm91bmQobWF4KGhhcF9pbmRfc3RhdHMkTG93X0NvdmVyYWdlLkVycm9ycywgbmEucm0gPSBUUlVFKS9ucm93KGhhcF9zdGF0cyksIGRpZ2l0cyA9IDQpKjEwMGAlIG9mIGxvY2kuCgojIyBGaWx0ZXIgZmxhZ2dlZCBsb2NpIGFuZCBpbmRpdmlkdWFscyBhcyBuZWNlc3NhcnkKCkxvYWQgZ2VuZXBvcCBmaWxlIHdpdGggaGFwbG90eXBlZCBsb2NpLgoKYGBge3IgbG9hZCBnZW5lcG9wLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBpbXBvcnQgZ2VuZXBvcCBmaWxlCmdlbiA8LSByZWFkLmdlbmVwb3AoZmlsZSA9ICJkYXRhL0hhcGxvdHlwaW5nL0JNQS5nZW4iLAogICAgICAgICAgICAgICAgICAgIG5jb2RlID0gM0wsIHF1aWV0ID0gRkFMU0UpCgpnZW4KCmBgYAoKUmVtb3ZlIGZsYWdnZWQgbG9jaSBhbmQgaW5kaXZpZHVhbHMuCgpgYGB7ciByZW1vdmUgbG9jaSBpbmRpdmlkdWFscywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgcmVtb3ZlIGZsYWdnZWQgbG9jaQpyZW1vdmVsb2MgPC0gYyhQb3NzX1BhcmFsb2dzLCBOb1NOcHMsIE5vSGFwcywgR2Vub19FcnIsIFByb3BfSGFwbG90eXBlZCkKCmdlbiA8LSBnZW5pbmQucmVtLmxvY2koZ2VuLCByZW1vdmVsb2MpCgojIHJlbW92ZSBmbGFnZ2VkIGluZGl2aWR1YWxzCnJlbW92ZUluZCA8LSBjKFBvc3NfUGFyYWxvZ0luZCwgUHJvcFN1Y2Nlc3NJbmQsIEdlbm9FcnJJbmR2LAogICAgICAgICAgICAgICAiQk1BXzFBLUgwMl9NUzE4IiwgIkJNQV8xQi1DMDVfTVMtMjIiLCAiQk1BXzFCLUMwM19NUy0yMCIsICJCTUFfM0EtRDAxX0JNMDA2IikKZ2VuIDwtIGdlbi5pbmQucmVtLkluZChnZW4sIHJlbW92ZUluZCkKCmdlbgoKYGBgCgojIENvbXBhcmUgZHVwbGljYXRlIGluZGl2aWR1YWxzCgpgYGB7ciBjb21wIGR1bHBsaWNhdGUgaW5kdiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgZXh0cmFjdCBnZW5vdHlwZSBtYXRyaXgKZGYgPC0gZ2VuaW5kMmRmKGdlbiwKICAgICAgICAgICAgICAgIHVzZXBvcCA9IFRSVUUsCiAgICAgICAgICAgICAgICBzZXAgPSAiOiIsIG9uZUNvbFBlckFsbCA9IEZBTFNFKSAlPiUKICBzZWxlY3QoLXBvcCkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCkKCiMgY3JlYXRlIGxpc3Qgb2YgZHVwbGljYXRlcwpwYWlycyA8LSBsaXN0KCkKCiMgaW5wdXQgZWFjaCBzZXQgb2YgZHVwbGljYXRlcyBhcyBhIHZlY3RvciBvZiBhIGxpc3QKcGFpcnNbWzFdXSA8LSBjKCJCTUFfM0ItRTEyX01TLTM3IiwgIkJNQV8yQS1DMDFfTVMtNTciKQpwYWlyc1tbMl1dIDwtIGMoIkJNQV8xQS1DMDFfQ0NHTi0wMDEiLCAiQk1BXzFBLUQwMl9DQ0dOMDEiKQpwYWlyc1tbM11dIDwtIGMoIkJNQV8xQS1IMDRfQ0MwMi0zNSIsCSJCTUFfMkItQjA5X0NDLTM1IikKcGFpcnNbWzRdXSA8LSBjKCJCTUFfM0ItSDAyX01TMjYiLCAiQk1BXzNCLUQwMV9NUzI2IikKcGFpcnNbWzVdXSA8LSBjKCJCTUFfMkItSDAyX01CMDYiLCAiQk1BXzFCLUUwNl9NQi0wNiIpCnBhaXJzW1s2XV0gPC0gYygiQk1BXzFCLUcxMV9DQy0wOCIsICJCTUFfMUEtSDAzX0NDMDItMDgiKQpwYWlyc1tbN11dIDwtIGMoIkJNQV8zQi1IMDNfQk0wMjciLCAiQk1BXzNCLUEwN19CTTAyNyIpCnBhaXJzW1s4XV0gPC0gYygiQk1BXzFCLUMwNF9NUy0yMSIsCSJCTUFfMkEtQzA1X01TLTYxIikKcGFpcnNbWzldXSA8LSBjKCJCTUFfMkItSDAxX0NTMyIsICJCTUFfMUEtQjAzX0NTLTAzIikKcGFpcnNbWzEwXV0gPC0gYygiQk1BXzNCLUUxMV9NUy0zNiIsICJCTUFfMUItQzEyX01TLTU2IikKcGFpcnNbWzExXV0gPC0gYygiQk1BXzJBLUMwN19NUy02MyIsICJCTUFfMUItQzA2X01TLTIzIikKcGFpcnNbWzEyXV0gPC0gYygiQk1BXzJCLUIwMV9DQy0xMiIsICJCTUFfM0EtQTAyX0NDLTEyIikKcGFpcnNbWzEzXV0gPC0gYygiQk1BXzJCLUcwNV9CTUFSLTAzIiwgIkJNQV8zQi1FMTJfQk1BUi0wMiIpCgoKIyBjcmVhdGUgZW1wdHkgbGlzdCBmb3IgZ2Vub3R5cGUgZXJyb3IgKGRpc2NvcmRhbnQgbG9jaSkKZ2Vub2Vycm9yIDwtIGxpc3QoKQoKIyBjcmVhdGUgZW1wdHkgdmVjdG9yIGZvciBkdXBsaWNhdGVzIChyZXRhaW5zIGZpcnN0IGluZHYgaW4gcGFpcikKZHVwIDwtIGNoYXJhY3RlcigpCgojIGlkZW50aWZ5IGRpc2NvcmRhbnQgZ2Vub3R5cGVzIGZvciBlYWNoIHNldCBvZiBkdXBsaWNhdGVzCmZvciAocCBpbiBwYWlycyl7CgojIHNlbGVjdCBkdXBsaWNhdGVzIGZyb20gZ2Vub3R5cGUgbWF0cml4Cmdlbm8gPC0gZGYgJT4lCiAgZmlsdGVyKHJvd25hbWUgJWluJSBwKSAlPiUKICBzZWxlY3QoLXJvd25hbWUpCgojIGNvbXBhcmUgZ2Vub3R5cGVzCmNvbXAgPC0gKHQoZ2VubykpCgpjb250aWdzIDwtIGFzLmRhdGEuZnJhbWUoY29tcCkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJMT0NVUyIpICU+JQogIG11dGF0ZShWMSA9IGFzLmNoYXJhY3RlcihWMSksCiAgICAgICAgIFYyID0gYXMuY2hhcmFjdGVyKFYyKSkgJT4lCiAgZmlsdGVyKFYxICE9IFYyKQoKIyB3cml0ZSB2ZWN0b3Igd2l0aCBmaXJzdCBpbmRpdmlkdWFsIGluIHBhaXIKaW5kIDwtIHBbMV0KCmR1cCA8LSBjKGR1cCwgaW5kKQoKZ2Vub2Vycm9yW1tpbmRdXSA8LSBjb250aWdzCgp9CgojIGlmIGl0IHRocm93cyBlcnJvciBvYmplY3QgVjEgb3IgVjIgbm90IGZvdW5kIGl0IG1lYW5zIG9uZSBvciBtb3JlIG9mIHRoZSBzYW1wbGVzIG5hbWVzIGFyZSBub3QgY29ycmVjdCBvciBubyBsb25nZXIgaW4gZGF0YSBzZXQgYWZ0ZXIgZmlsdGVyaW5nCgojIGNvbWJpbmUgaW50byBvbmUgZGF0YWZyYW1lCmdlbm9lcnJvciA8LSBsZHBseShnZW5vZXJyb3IsIGRhdGEuZnJhbWUpICU+JQogIHJlbmFtZShEVVAxID0gYC5pZGAsCiAgICAgICAgIEdFTk9fSU5EVjEgPSBWMSwKICAgICAgICAgR0VOT19JTkRWMiA9IFYyKQoKd3JpdGVfZGVsaW0oZ2Vub2Vycm9yLCAicmVzdWx0cy9oYXBsb3R5cGVkLmdlbm9lcnJvciIsIGRlbGltID0gIlx0IikKCmBgYAoKQ29tcGFyZSBnZW5vdHlwZSBkZXB0aCBmb3IgZGlzY29yZGFudCBsb2NpOgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgaW1wb3J0IGdlbm90eXBlIGRlcHRoIGtlZXAgb25lIGRlcHRoIHBlciBjb250aWcKbiA8LSBucm93KGluZF9zdGF0c19GMTMpICsgMQoKZ2RlcHRoIDwtIHJlYWRfdGFibGUyKCJkYXRhL1ZDRi9CTUEuRjEzLmdkZXB0aCIpICU+JQogIHNlbGVjdCgtUE9TKSAlPiUKICBkaXN0aW5jdChDSFJPTSwgLmtlZXBfYWxsID0gVFJVRSkgJT4lCiAgZ2F0aGVyKGtleSA9IElORFYsIHZhbHVlID0gR0RFUFRILCAyOm4pICU+JQogIHJlbmFtZShMT0NVUyA9IENIUk9NKQoKIyBjcmVhdGUgZGF0YWZyYW1lIHdpdGggZHVwbGljYXRlcwpkdXBfaW5kdiA8LSBkYXRhLmZyYW1lKG1hdHJpeChuY29sID0gMiwgbnJvdyA9IDApKQpjb2xuYW1lcyhkdXBfaW5kdikgPC0gYygiRFVQMSIsICJEVVAyIikKCmZvciAocCBpbiBwYWlycyl7CgpwIDwtIGFzLmRhdGEuZnJhbWUodChwKSkKCmNvbG5hbWVzKHApIDwtICBjKCJEVVAxIiwgIkRVUDIiKQoKZHVwX2luZHYgPC0gYmluZF9yb3dzKGR1cF9pbmR2LCBwKQogICAKfQoKIyBhZGQgZHVwbGljYXRlIDIgdG8gZ2Vub2Vycm9yIGRhdGEgZnJhbWUKZ2Vub2Vycm9yIDwtIGxlZnRfam9pbihnZW5vZXJyb3IsIGR1cF9pbmR2KQoKIyBhZGQgZ2Vub3R5cGUgZGVwdGggaW5mb3JtYXRpb24gZm9yIGR1cGxpY2F0ZSAxCmdkZXB0aCA8LSBnZGVwdGggJT4lCiAgcmVuYW1lKERVUDEgPSBJTkRWKQoKZ2Vub2Vycm9yIDwtIGxlZnRfam9pbihnZW5vZXJyb3IsIGdkZXB0aCkgJT4lCiAgcmVuYW1lKEdERVBUSDEgPSBHREVQVEgpCgojIGFkZCBnZW5vdHlwZSBkZXB0aCBpbmZvcm1hdGlvbiBmb3IgZHVwbGljYXRlIDIKZ2RlcHRoIDwtIGdkZXB0aCAlPiUKICByZW5hbWUoRFVQMiA9IERVUDEpCgpnZW5vZXJyb3IgPC0gbGVmdF9qb2luKGdlbm9lcnJvciwgZ2RlcHRoKSAlPiUKICByZW5hbWUoR0RFUFRIMiA9IEdERVBUSCkKCiMgaWRlbnRpZnkgaG9tb3p5Z290ZSB2cyBoZXRlcm96eWdvdGUgZ2Vub3R5cGVzCmdlbm9lcnJvciA8LSBnZW5vZXJyb3IgJT4lCiAgc2VwYXJhdGUoY29sID0gR0VOT19JTkRWMSwgaW50byA9IGMoIkdFTk8xYSIsICJHRU5PMWIiKSwgc2VwID0gIjoiLCByZW1vdmUgPSBGQUxTRSkgJT4lCiAgc2VwYXJhdGUoY29sID0gR0VOT19JTkRWMiwgaW50byA9IGMoIkdFTk8yYSIsICJHRU5PMmIiKSwgc2VwID0gIjoiLCByZW1vdmUgPSBGQUxTRSkgJT4lCiAgbXV0YXRlKEdFTk9UWVBFMSA9IGlmZWxzZShHRU5PMWEgPT0gR0VOTzFiLCAiSE9NT1pZR09URSIsICJIRVRFUk9aWUdPVEUiKSwKICAgICAgICAgR0VOT1RZUEUyID0gaWZlbHNlKEdFTk8yYSA9PSBHRU5PMmIsICJIT01PWllHT1RFIiwgIkhFVEVST1pZR09URSIpKQoKYGBgCgpEZXRlcm1pbmUgbnVtYmVyIG9mIHRpbWVzIGRpc2NvcmRhbnQgZ2Vub3R5cGUgaXMgZHVlIHRvIGhldGVyb3p5Z290ZS9ob21venlnb3RlLgoKYGBge3J9Cgpjb3VudChnZW5vZXJyb3IsIEdFTk9UWVBFMSA9PSBHRU5PVFlQRTIpCgpgYGAKCkNvbXBhcmUgbnVtYmVyIG9mIGRpc2NvcmRhbnQgZ2Vub3R5cGUgY2FsbHMgcGVyIGR1cGxpY2F0ZSBzZXQuCgpgYGB7ciwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NH0KCnRvdGFsIDwtIGFzLm51bWVyaWMobGVuZ3RoKGxvY05hbWVzKGdlbikpKQoKIyBjb21wYXIgbnVtYmVyIG9mIGxvY2kgYnkgcGFpcgpwZXJfaW5kIDwtIGNvdW50KGdlbm9lcnJvciwgRFVQMSkgJT4lCiAgbXV0YXRlKGZyZXEgPSBuL3RvdGFsKjEwMCkKCmdncGxvdChwZXJfaW5kLCBhZXMoZnJlcSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMjUsIGZpbGwgPSAiZGFya29yYW5nZSIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDUpKSArCiAgbGFicyh4ID0gIiUgZ2Vub3R5cGluZyBlcnJvciBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpJZGVudGlmeSBsb2NpIGNvbnNpc3RlbnRseSBhZmZlY3RlZCBieSBnZW5vdHlwaW5nIGVycm9yCgpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKdG90YWwgPC0gYXMubnVtZXJpYyhsZW5ndGgocGFpcnMpKQoKIyBjb21wYXJlIGxvY2kgYWZmZWN0ZWQgYnkgZ2Vub3R5cGluZyBlcnJvcgpwZXJfbG9jIDwtIGNvdW50KGdlbm9lcnJvciwgTE9DVVMpICU+JQogIG11dGF0ZShmcmVxID0gbi90b3RhbCoxMDApICU+JQogIHJlbmFtZShMb2N1cyA9IExPQ1VTKQoKcGVyX2xvYyA8LSBsZWZ0X2pvaW4ocGVyX2xvYywgaGFwX3N0YXRzKQoKZ2dwbG90KHBlcl9sb2MsIGFlcyh4ID0gbikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAiZGFya29yYW5nZSIsIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKG4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gInNhbWUgbG9jdXMgYWZmZWN0ZWQgaW4gbiBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCmBgYHtyfQoKY291bnQocGVyX2xvYywgbiA+IDMpCgpgYGAKClJlbW92ZSBmbGFnZ2VkIGxvY2kgYW5kIG9uZSBpbmRpdmlkdWFsIHBlciBwYWlyLgoKYGBge3J9CgojIHdyaXRlIHZlY3RvciB3aXRoIHNlY29uZCBpbmRpdmlkdWFsIGluIHBhaXIgKGxvd2VyIHF1YWxpdHkpCnJtIDwtIGMoIkJNQV8yQS1DMDFfTVMtNTciLCAiQk1BXzFBLUQwMl9DQ0dOMDEiLCAiQk1BXzJCLUIwOV9DQy0zNSIsICJCTUFfM0ItRDAxX01TMjYiLCAiQk1BXzFCLUUwNl9NQi0wNiIsCiAgICAgICAgIkJNQV8xQS1IMDNfQ0MwMi0wOCIsICJCTUFfM0ItQTA3X0JNMDI3IiwgIkJNQV8yQS1DMDVfTVMtNjEiLCAiQk1BXzFBLUIwM19DUy0wMyIsICJCTUFfMUItQzEyX01TLTU2IiwKICAgICAgICAiQk1BXzFCLUMwNl9NUy0yMyIsICJCTUFfM0EtQTAyX0NDLTEyIiwgIkJNQV8zQi1FMTJfQk1BUi0wMiIpCgojIHJlbW92ZSBkdXBsaWNhdGVzCnJlbW92ZUluZCA8LSBybQoKZ2VuIDwtIGdlbi5pbmQucmVtLkluZChnZW4sIHJlbW92ZUluZCkKCiMgcmVtb3ZlIGZsYWdnZWQgbG9jaQpyZW1vdmVsb2MgPC0gZmlsdGVyKHBlcl9sb2MsIG4gPiAzKQpnZW4gPC0gZ2VuaW5kLnJlbS5sb2NpKGdlbiwgcmVtb3ZlbG9jKQoKZ2VuCgpgYGAKCmByIG5yb3codGVtcClgIGxvY2kgd2VyZSByZW1vdmVkIGFzIHBvdGVudGlhbGx5IGFmZmVjdGVkIGJ5IGdlbm90eXBpbmcgZXJyb3IuCgojIFJlbGF0ZWRuZXNzICYgSW5icmVlZGluZwoKQ3JlYXRlIGlucHV0IGZpbGUgZm9yZSBgcmVsYXRlZGAgcGFja2FnZS4KCmBgYHtyfQoKIyBuZWVkIHRvIGNoYW5nZSB0byBSIDMyCmxpYnJhcnkocmVsYXRlZCkKCiMgY3JlYXRlIGlucHV0IGZpbGUgLS0tLQpkZiA8LSBnZW5pbmQyZGYoZ2VuLCB1c2Vwb3AgPSBGQUxTRSwgb25lQ29sUGVyQWxsID0gVFJVRSkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCJJTkRWIikgJT4lCiAgc2VwYXJhdGUoSU5EViwgaW50byA9IGMoIlBPUCIsICJMSUIiLCAiSU5EViIpLCBzZXAgPSAiXyIsIGV4dHJhID0gIm1lcmdlIikgJT4lCiAgc2VsZWN0KC1QT1ApICU+JQogIHVuaXRlKElORCwgTElCLCBJTkRWLCBzZXAgPSAiXyIpCgojIG1pc3NpbmcgZGF0YSBtdXN0IGJlIDAKZGZbZGY9PSJOQSJdIDwtIDAKCndyaXRlLnRhYmxlKGRmLCAic2NyYXRjaC9yZWxhdGVkLmlucHV0IiwKICAgICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBzZXAgPSAiXHQiLCBxdW90ZSA9IEZBTFNFKQoKIyBpbXBvcnQgaW5wdXQgZmlsZSBhcyBsaXN0IChnZGF0YSwgbmxvY2ksIG5hbGxlbGVzLCBuaW5kcywgZnJlcXMpCmdlbm90eXBlZGF0YSA8LSByZWFkZ2Vub3R5cGVkYXRhKCJzY3JhdGNoL3JlbGF0ZWQuaW5wdXQiKQoKYGBgCgpDYWxjdWxhdGUgcGFpcndpc2UgcmVsYXRlZG5lc3MgYWNjb3JkaW5nIHRvIEx5bmNoICYgUml0bGFuZCAxOTk5OyB1c2VzIGluYnJlZWRpbmcgZXN0aW1hdGVzIGZvciBlYWNoIGluZGl2aWR1YWxzIHRvIGVzdGltYXRlIHJlbGF0ZWRuZXNzLgoKYGBge3IgbHluY2hyZCwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9N30KCiMgcGFpcndpc2UgcmVsYXRlZG5lc3MgKEx5bmNoICYgUml0bGFuZCAxOTk5KQpyZWxhdGVkbmVzc19seW5jaHJkIDwtIGNvYW5jZXN0cnkoZ2Vub3R5cGVkYXRhJGdkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHluY2hyZCA9IDEpCgpyZWxhdGVkbiA8LSByZWxhdGVkbmVzc19seW5jaHJkJHJlbGF0ZWRuZXNzICU+JQogIHNlbGVjdChwYWlyLm5vLCBpbmQxLmlkLCBpbmQyLmlkLCBseW5jaHJkKQoKd3JpdGVfZGVsaW0ocmVsYXRlZG4sICJyZXN1bHRzL3BhaXJ3aXNlX3JlbGF0ZWRuZXNzIikKCmluYnJlZWQgPC0gcmVsYXRlZG5lc3NfbHluY2hyZCRpbmJyZWVkaW5nICU+JQogIHNlbGVjdChpbmQuaWQsIEwzLCBMSCkgJT4lCiAgcmVuYW1lKElORFYgPSBpbmQuaWQpCgp3cml0ZV9kZWxpbShpbmJyZWVkLCAicmVzdWx0cy9pbmJyZWVkaW5nIikKCmBgYAoKRGlzdHJpYnV0aW9uIG9mIGxldmVscyBvZiBwYWlyd2lzZSByZWxhdGVkbmVzczoKCmBgYHtyIGx5bmNocmQgZGlzdHJpYiByZWxhdGVkbiwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9OH0KCmdncGxvdChyZWxhdGVkbiwgYWVzKHggPSBseW5jaHJkKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMDI1LCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihseW5jaHJkLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gcXVhbnRpbGUobHluY2hyZCwgMC45NSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgc2NhbGVfeV9zcXJ0KCkgKwogIGxhYnMoeCA9ICJyZWxhdGVkbmVzcyIsIHkgPSAibnVtYmVyIG9mIHBhaXJzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCkRpc3RyaWJ1dGlvbiBvZiBsZXZlbHMgb2YgaG9tb3p5Z29zaXR5OgoKYGBge3IgbHluY2hyZCBpbmJyZWVkaW5nLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00fQoKZ2dwbG90KGluYnJlZWQsIGFlcyh4ID0gTDMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAwNSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTEgsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBxdWFudGlsZShMSCwgMC45NSkpLAogICAgICAgICAgICAgY29sb3IgPSAiZGFya3JlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gImluYnJlZWRpbmcgY29lZmZpY2llbnQiLCB5ID0gImluZGl2aWR1YWxzIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKCiMgSGV0ZXJvenlnb3NpdHkgYW5kIEhXRQoKR2VuZXJhdGUgc3VtbWFyeSBzdGF0aXN0aWNzCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KClNhbXBsZUluZm8gPC0gcmVhZF9kZWxpbSgiZGF0YS9QT1BHRU4vU2FtcGxlSW5mby50eHQiLCBkZWxpbSA9ICJcdCIpICU+JQogIGRpc3RpbmN0KFNBTVBMRV9JRCwgLmtlZXBfYWxsID0gVFJVRSkKCkluZHMgPC0gYXMuZGF0YS5mcmFtZShpbmROYW1lcyhnZW4pKSAlPiUKICByZW5hbWUoTElCX0lEID0gYGluZE5hbWVzKGdlbilgKSAlPiUKICBzZXBhcmF0ZShMSUJfSUQsIGludG8gPSBjKCJTUCIsICJXRUxMIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIGV4dHJhID0gIm1lcmdlIiwgcmVtb3ZlID0gRkFMU0UpCgpzdHJhdGEgPC0gbGVmdF9qb2luKEluZHMsIFNhbXBsZUluZm8pICU+JQogIGRpc3RpbmN0KCkgJT4lCiAgbXV0YXRlKFBPUCA9IG9yZGVyZWQoUE9QLCBsZXZlbHMgPSBwb3BzKSkgJT4lCiAgbXV0YXRlKFJFR0lPTiA9IGNhc2Vfd2hlbihQT1AgJWluJSBjKCJGTEEiKSB+ICJTV0FUTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQT1AgJWluJSBjKCJDQU1QIikgfiAiU0dVTEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9QICVpbiUgYygiRkxHUyIsICJGTEdOIikgfiAiRUdVTEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9QICVpbiUgYygiTUIiLCAiTUlTUyIsICJDUyIsICJMQSIpIH4gIkNHVUxGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBPUCAlaW4lIGMoIkNDIikgfiAiV0dVTEYiLCksCiAgICAgICAgIE9DRUFOID0gaWZlbHNlKFBPUCA9PSAiRkxBIiwgIkFUTCIsICJHVUxGIikpCgpzdHJhdGEoZ2VuKSA8LSBzdHJhdGEKCiMgZGVmaW5lIGdyb3VwcyB1c2luZyBzdHJhdGEgaW5mb3JtYXRpb24gLSBuZWVkIHRvIGFkZCBQT1AgZm9yIG1pc3Npbmcgb25lcwpzZXRQb3AoZ2VuKSA8LSB+UE9QCgojIGdlbmVyYXRlIGdlbmV0aWMgZGl2ZXJzaXR5IHN0YXRzCkdlbkRpdiA8LSBhZGVnZW5ldDo6c3VtbWFyeShnZW4pCgpkYXQgPC0gaGllcmZzdGF0Ojo6LmdlbmluZDJoaWVyZnN0YXQoZ2VuKQpHZW5EaXYyIDwtIGJhc2ljLnN0YXRzKGRhdCkKCmBgYAoKQ29tcGFyZSBvYnNlcnZlZCAoSG8pIGFuZCBleHBlY3RlZCAoSGUpIGhldGVyb3p5Z29zaXR5IGZvciBhbGwgaW5kaXZpZHVhbHMgYWNyb3NzIGFsbCBwb3B1bGF0aW9ucy4KCmBgYHtyfQoKIyBvYnNlcnZlZCBoZXRlcm96eWdvc2l0eSBwZXIgbG9jdXMKSG8gPC0gYXMuZGF0YS5mcmFtZShHZW5EaXYkSG9icykgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigiTE9DVVMiKSAlPiUKICByZW5hbWUoSG8gPSBgR2VuRGl2JEhvYnNgKQoKIyBleHBlY3RlZCBoZXRlcm96eWdvc2l0eSBwZXIgbG9jdXMKSHMgPC0gYXMuZGF0YS5mcmFtZShHZW5EaXYkSGV4cCkgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigiTE9DVVMiKSAlPiUKICByZW5hbWUoSGV4cCA9IGBHZW5EaXYkSGV4cGApCgojIGV4cGVjdGVkIGFuZCBvYnNlcnZlZCBoZXRlcm96eXNpdHkgcGVyIGxvY3VzCkhldCA8LSBsZWZ0X2pvaW4oSG8sIEhzLCBieSA9ICJMT0NVUyIpCgpgYGAKCklkZW50aWZ5IGxvY2kgdGhhdCBhcmUgbm93IG1vbm9tb3JwaGljIGFuZCByZW1vdmUgZnJvbSBkYXRhIHNldDoKCmBgYHtyfQoKbW9ub21vcnBoaWMgPC0gZmlsdGVyKEhvLCBIbyA9PSAwKQoKbW9ub21vcnBoaWMgPC0gbW9ub21vcnBoaWMkTE9DVVMKCiMgcmVtb3ZlIGZsYWdnZWQgbG9jaQpyZW1vdmVsb2MgPC0gYyhtb25vbW9ycGhpYykKZ2VuIDwtIGdlbmluZC5yZW0ubG9jaShnZW4sIHJlbW92ZWxvYykKCmdlbgoKYGBgCgpFeHBlY3RlZCB2cyBvYnNlcnZlZCBoZXRlcm96eWdvc2l0eSBhY3Jvc3MgYWxsIHBvcHVsYXRpb25zLgoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NH0KCnRlbXAgPC0gSGV0ICU+JQogIGZpbHRlcihIbyAhPSAwKQoKIyBwbG90IEhvIHZzIEhzIGFjcm9zcyBhbGwgaW5kaXZpZHVhbHMKZ2dwbG90KHRlbXAsIGFlcyh4ID0gSG8sIHkgPSBIZXhwKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHhsaW0oMCwgMSkgKwogIHlsaW0oMCwgMSkgKwogIGxhYnMoeCA9ICJvYnNlcnZlZCBoZXRlcm96eWdvc2l0eSBIbyIsIHkgPSAid2l0aGluIGNsdXN0ZXIgZGl2ZXJzaXR5IEhzIChIZXhwKSIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBvYnNlcnZlZCBoZXRlcm96eWdvc2l0eSAoSG8pIGluIGVhY2ggcHV0YXRpdmUgcG9wdWxhdGlvbjoKCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTR9CgpIb19wZXIgPC0gYXMuZGF0YS5mcmFtZShHZW5EaXYyJEhvKSAlPiUKICByb3duYW1lc190b19jb2x1bW4oIkxPQ1VTIikgJT4lCiAgcmVuYW1lKENBTVAgPSBgMWAsIEZMR1MgPSBgMmAsIEZMR04gPSBgM2AsIEZMQSA9IGA0YCwgQ1MgPSBgNWAsIAogICAgICAgICBDQyA9IGA2YCwgTUlTUyA9IGA3YCwgTEEgPSBgOGAsIE1CID0gYDlgKSAlPiUKICBzZWxlY3QoTE9DVVMsIENBTVAsIEZMR1MsIEZMR04sIEZMQSwgQ1MsIENDLCBNSVNTLCBMQSwgTUIpICU+JQogIGdhdGhlcihHcm91cCwgSG8sIDI6MTApICU+JQogIG11dGF0ZShQT1AgPSBvcmRlcmVkKEdyb3VwLCBsZXZlbHMgPSBwb3BzKSkgJT4lCiAgbXV0YXRlKFJFR0lPTiA9IGNhc2Vfd2hlbihQT1AgJWluJSBjKCJGTEEiKSB+ICJTV0FUTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQT1AgJWluJSBjKCJDQU1QIikgfiAiU0dVTEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9QICVpbiUgYygiRkxHUyIsICJGTEdOIikgfiAiRUdVTEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUE9QICVpbiUgYygiTUIiLCAiTUlTUyIsICJDUyIsICJMQSIpIH4gIkNHVUxGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBPUCAlaW4lIGMoIkNDIikgfiAiV0dVTEYiLCksCiAgICAgICAgIE9DRUFOID0gaWZlbHNlKFBPUCA9PSAiRkxBIiwgIkFUTCIsICJHVUxGIikpCgojIGNvbXBhcmUgb2JzZXJ2ZWQgaGV0ZXJvenlnb3NpdHkgcGVyIGxvY3VzIGFuZCBjbHVzdGVyCmdncGxvdChIb19wZXIsIGFlcyh4ID0gR3JvdXAsIHkgPSBIbywgZmlsbCA9IFJFR0lPTikpICsKICBnZW9tX2JveHBsb3QoKSArCiAgbGFicyh4ID0gIkdyb3VwIiwgeSA9ICJIbyIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xfcmVncykgKwogIHRoZW1lX3N0YW5kYXJkICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKQoKYGBgCgpDb21wYXJlIGRpc3RyaWJ1dGlvbiBvZiBleHBlY3RlZCBoZXRlcm96eWdvc2l0eSBIZSwgKHdpdGhpbiBjbHVzdGVyIGRpdmVyc2l0eSkgaW4gZWFjaCBwdXRhdGl2ZSBwb3B1bGF0aW9uOgoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NX0KCiMgd2l0aGluIGNsdXN0ZXIgZGl2ZXJzaXR5L2V4cCBkaXZlcnNpdHkgcGVyIGxvY3VzIChyb3dzKSBhbmQgY2x1c3RlciAoY29sdW1ucykKSHNfcGVyIDwtIGFzLmRhdGEuZnJhbWUoR2VuRGl2MiRIcykgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCJMT0NVUyIpICU+JQogIHJlbmFtZShDQU1QID0gYDFgLCBGTEdTID0gYDJgLCBGTEdOID0gYDNgLCBGTEEgPSBgNGAsIENTID0gYDVgLCAKICAgICAgICAgQ0MgPSBgNmAsIE1JU1MgPSBgN2AsIExBID0gYDhgLCBNQiA9IGA5YCkgJT4lCiAgc2VsZWN0KExPQ1VTLCBDQU1QLCBGTEdTLCBGTEdOLCBGTEEsIENTLCBDQywgTUlTUywgTEEsIE1CKSAlPiUKICBnYXRoZXIoR3JvdXAsIEhzLCAyOjkpCgojIGNvbXBhcmUgZXhwZWN0ZWQgaGV0ZXJvenlnb3NpdHkgcGVyIGxvY3VzIGFuZCBjbHVzdGVyCmdncGxvdChIc19wZXIsIGFlcyh4ID0gR3JvdXAsIHkgPSBIcykpICsKICBnZW9tX2JveHBsb3QoKSArCiAgbGFicyh4ID0gIkdyb3VwIiwgeSA9ICJleHBlY3RlZCBoZXRlcm96eWdvc2l0eSBIbyIpICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpDb21wYXJpc29uIG9mIG9iZXJ2ZWQgdnMuIGhldGVyb3p5Z29zaXR5IHdpdGhpbiBlYWNoIHBvcHVsYXRpb246CgpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGpvaW4gZGF0YSBmcmFtZXMKSGV0X3BlciA8LSBsZWZ0X2pvaW4oSHNfcGVyLCBIb19wZXIpCgojIHBsb3QgcGVyIGNsdXN0ZXIKZ2dwbG90KEhldF9wZXIsIGFlcyh4ID0gSG8sIHkgPSBIcykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMTksIHNpemUgPSAxKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIHhsaW0oMCwgMSkgKwogIHlsaW0oMCwgMSkgKwogIGZhY2V0X2dyaWQoLiB+IEdyb3VwKSArCiAgbGFicyh4ID0gIm9ic2VydmVkIGhldGVyb3p5Z29zaXR5IEhvIiwgeSA9ICJ3aXRoaW4gY2x1c3RlciBkaXZlcnNpdHkgSHMgKEhleHApIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKClRlc3QgZm9yIGRldmlhdGlvbnMgZnJvbSBIYXJkeS1XZWluYmVyZyBlcXVpbGlicml1bSB3aXRoaW4gZWFjaCBncm91cCAoUE9QIGxldmVsKToKCmBgYHtyfQoKc2V0UG9wKGdlbikgPC0gflBPUAoKcG9wTmFtZXMoZ2VuKQoKIyBzaG91bGQgYmUgYWJsZSB0byB1c2UgbGFwcGx5CkhXRSA8LSBzZXBwb3AoZ2VuKSAlPiUKICAgbGFwcGx5KGh3LnRlc3QsIEI9MTAwMCkKCkhXRVtbIkFMTCJdXSA8LSBody50ZXN0KGdlbiwgQiA9IDEwMDApCgojIGNvbnZlcnQgdG8gZGF0YS5mcmFtZXMKaHdlIDwtIGxpc3QoKQoKZm9yIChtIGluIG5hbWVzKEhXRSkpIHsKICAgaHdlW1ttXV0gPC0gYXMuZGF0YS5mcmFtZShIV0VbW21dXSkgJT4lCiAgIHJlbmFtZShwdmFsID0gUHIuZXhhY3QpICU+JQogICByb3duYW1lc190b19jb2x1bW4oIkxPQ1VTIikgJT4lCiAgIHNlbGVjdChMT0NVUywgcHZhbCkKfQoKaHdlIDwtIGxkcGx5KGh3ZSwgZGF0YS5mcmFtZSkgJT4lCiAgIHJlbmFtZShQT1AgPSBgLmlkYCkgJT4lCiAgIG11dGF0ZShIV0UgPSBpZmVsc2UocHZhbCA8PSAwLjA1LCAiT1VUIiwgIklOIikpCgp3cml0ZV9kZWxpbShod2UsICJyZXN1bHRzL0hXRWJ5cG9wIiwgZGVsaW0gPSAiXHQiKQoKaHdlIDwtIHJlYWRfZGVsaW0oInJlc3VsdHMvSFdFYnlwb3AiLCBkZWxpbSA9ICJcdCIpCgpod2VfcGVycG9wIDwtIGh3ZSAlPiUKICBncm91cF9ieShQT1ApICU+JQogIGNvdW50KEhXRSkKCmh3ZV9wZXJsb2MgPC0gaHdlICU+JQogIGZpbHRlcihQT1AgIT0gIkFMTCIpICU+JQogIGdyb3VwX2J5KExPQ1VTKSAlPiUKICBjb3VudChIV0UpICU+JQogIGZpbHRlcihIV0UgPT0gIk9VVCIpCgpgYGAKCkZvcm1hdCBvdXRwdXQgYW5kIHZpZXcgcmVzdWx0czoKCmBgYHtyIEhXRSByZXN1bHRzLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0xMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgcGxvdCBkYXRhCmdncGxvdChod2VfcGVycG9wLCBhZXMoeCA9IEhXRSwgeSA9IG4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGxhYnMoeCA9ICJzaWduaWZpY2FudCBkZXZpYXRpb24gZnJvbSBIV0UgKHAgPiAwLjA1KSIsIHkgPSAibnVtYmVyIG9mIGxvY2kiKSArCiAgZmFjZXRfZ3JpZCggfiBQT1ApICsKICB0aGVtZV9zdGFuZGFyZAoKYGBgCgpEaXN0cmlidXRpb24gb2YgbnVtYmVyIG9mIHRpbWVzIGxvY2kgYXJlIG91dCBvZiBIV0UKCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTR9CgpnZ3Bsb3QoaHdlX3BlcmxvYywgYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgbGFicyh4ID0gIm5vIHBvcHVsYXRpb25zIG91dCBvZiBIV0UiLCB5ID0gIm5vLiBsb2NpIikgKwogIHRoZW1lX3N0YW5kYXJkCgpgYGAKClJlbW92ZSBsb2NpIG91dCBvZiBIV0UgaW4gNSBvciBtb3JlIHBvcHVsYXRpb25zOgoKYGBge3J9CgojIHJlbW92ZSBmbGFnZ2VkIGxvY2kKcmVtb3ZlbG9jIDwtIGh3ZV9wZXJsb2MgJT4lCiAgZmlsdGVyKG4gPj0gNSkKCmdlbiA8LSBnZW5pbmQucmVtLmxvY2koZ2VuLCByZW1vdmVsb2MkTE9DVVMpCgpnZW4KCmBgYAoKIyBGaW5hbCBkYXRhIHNldAoKV3JpdGUgZmlsZXMgd2l0aCBmaWx0ZXJlZCBkYXRhIHNldDoKCmBgYHtyIHdyaXRlIGZpbHRlcmVkIGRhdGEgc2V0fQoKbGlicmFyeShyYWRpYXRvcikKCnNldFBvcChnZW4pIDwtIH5QT1AKCiMgY29udmVydCB0byB0aWR5IGRhdGEgc2V0CnRpZHkgPC0gdGlkeV9nZW5vbWljX2RhdGEoZGF0YSA9IGdlbiwgZmlsZW5hbWUgPSBOVUxMKSAlPiUKICBkcGx5cjo6c2VsZWN0KDE6NikKCiMgd3JpdGUgdGlkeSBkYXRhIHNldCB0byBmaWxlCndyaXRlX2RlbGltKHRpZHksICJkYXRhL1BPUEdFTi9CTUEudGlkeS5nZW5vdHlweWVzIiwgZGVsaW0gPSAiXHQiKQoKIyB3cml0ZSBnZW5lcG9wIGZpbGUKd3JpdGVfZ2VuZXBvcChkYXRhID0gdGlkeSwKICAgICAgICAgICAgICBmaWxlbmFtZSA9ICJkYXRhL1BPUEdFTi9CTUFfYnlfcG9wIiwKICAgICAgICAgICAgICBnZW5lcG9wLmhlYWRlciA9ICJnYWZmdG9wIHNhaWwgY2F0ZmlzaCBncm91cGVkIGJ5IHBvcHVsYXRpb24iKQoKYGBgCgpXcml0ZSBmaWxlcyB3aXRoIGluZGl2aWR1YWxzIGFuZCBDb250aWdzIHN0aWxsIGNvbnRhaW5lZCBpbiBkYXRhIHNldCBhbmQgdXNlIHRvIGZpbHRlciB2Y2YgZmlsZS4KCmBgYHtyfQoKa2VlcGxvY2kgPC0gYXMuZGF0YS5mcmFtZShsb2NOYW1lcyhnZW4pKSAlPiUKICByZW5hbWUoTE9DVVMgPSBgbG9jTmFtZXMoZ2VuKWApCgprZWVwbG9jaSA8LSBmaWx0ZXIobG9jX3N0YXRzX0YxMywgQ0hSICVpbiUga2VlcGxvY2kkTE9DVVMpICU+JQogIHNlbGVjdChDSFIsIFBPUykKCndyaXRlLnRhYmxlKGtlZXBsb2NpLCAiZGF0YS9WQ0YvZmlsdGVyZWQubG9jaSIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCmtlZXBpbmQgPC0gYXMuZGF0YS5mcmFtZShpbmROYW1lcyhnZW4pKSAlPiUKICByZW5hbWUoTElCX0lEID0gYGluZE5hbWVzKGdlbilgKSAKCmtlZXBpbmQgPC1maWx0ZXIoaW5kX3N0YXRzX0YxMywgSU5EViAlaW4lIGtlZXBpbmQkTElCX0lEKSAlPiUKICBzZWxlY3QoSU5EVikKCndyaXRlLnRhYmxlKGtlZXBpbmQsICJkYXRhL1ZDRi9maWx0ZXJlZC5pbmQiLAogICAgICAgICAgICBjb2wubmFtZXMgPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCgpgYGAKCldyaXRlIHZjZiBmaWxlIGFuZCAwMTIgZm9ybWF0OgoKYGBge2Jhc2h9Cgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5GMTMucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi90ZW1wL0JNQSAtLXBvc2l0aW9ucyBkYXRhL1ZDRi9maWx0ZXJlZC5sb2NpIC0ta2VlcCBkYXRhL1ZDRi9maWx0ZXJlZC5pbmQgLS1yZWNvZGUgLS1yZWNvZGUtSU5GTy1hbGwKCnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9QT1BHRU4vQk1BIC0tMDEyCgp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5maWwgLS1kZXB0aAp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5maWwgLS1zaXRlLW1lYW4tZGVwdGgKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuZmlsIC0tbWlzc2luZy1pbmR2CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLmZpbCAtLW1pc3Npbmctc2l0ZQp2Y2Z0b29scyAtLXZjZiBkYXRhL1ZDRi90ZW1wL0JNQS5yZWNvZGUudmNmIC0tb3V0IGRhdGEvVkNGL0JNQS5maWwgLS1oZXQKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuZmlsIC0taGFyZHkKdmNmdG9vbHMgLS12Y2YgZGF0YS9WQ0YvdGVtcC9CTUEucmVjb2RlLnZjZiAtLW91dCBkYXRhL1ZDRi9CTUEuZmlsIC0tc2l0ZS1xdWFsaXR5CnZjZnRvb2xzIC0tdmNmIGRhdGEvVkNGL3RlbXAvQk1BLnJlY29kZS52Y2YgLS1vdXQgZGF0YS9WQ0YvQk1BLmZpbCAtLWdlbm8tZGVwdGgKCmBgYAoKQ29tcGFyZSBzdGF0cyBmb3IgZmluYWwgZmlsdGVyZWQgZGF0YSBzZXQ6CiAgICAKYGBge3Igc3RhdHMgZmluYWwsIGZpZy5oZWlnaHQ9MjAsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMgbG9hZCBzdGF0cyBmaWxlcyAtLS0tCmluZF9zdGF0c19maWwgPC0gcmVhZC5pbmQuc3RhdHMoZGlyID0gImRhdGEvVkNGIiwgdmNmID0gIkJNQS5maWwiKSAlPiUKICBzZXBhcmF0ZShJTkRWLCBpbnRvID0gYygiU1AiLCAiTElCIiwgIlNBTVBMRV9JRCIpLCBzZXAgPSAiXyIsIHJlbW92ZSA9IEZBTFNFKQoKbG9jX3N0YXRzX2ZpbCA8LSByZWFkLmxvYy5zdGF0cyhkaXIgPSAiZGF0YS9WQ0YvIiwgdmNmID0gIkJNQS5maWwiKQoKVmlldyhpbmRfc3RhdHNfZmlsKQpWaWV3KGhhcF9pbmRfc3RhdHMpCgojIHBsb3QgbWlzc2luZyBkYXRhIHBlciBpbmR2IC0tLS0KcDEgPC0gZ2dwbG90KGluZF9zdGF0c19maWwsIGFlcyh4ID0gTUlTU19CTUEuZmlsKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gLjAxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZGFya29yYW5nZSIpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihNSVNTX0JNQS5maWwsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDAuMjUpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWlzc2luZyBkYXRhIHBlciBpbmR2IikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgRmlzIHBlciBpbmR2IC0tLS0KcDIgPC0gZ2dwbG90KGluZF9zdGF0c19maWwsIGFlcyh4ID0gRmlzX0JNQS5maWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMDEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKEZpc19CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIkZpcyBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggcGVyIGluZHYgLS0tLQpwMyA8LSBnZ3Bsb3QoaW5kX3N0YXRzX2ZpbCwgYWVzKHggPSBNRUFOX0RFUFRIX0JNQS5maWwpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMCwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIHJlYWQgZGVwdGggcGVyIGluZHYiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBkZXB0aCB2cyBtaXNzaW5nIC0tLS0KcDQgPC0gZ2dwbG90KGluZF9zdGF0c19maWwsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuZmlsLCB5ID0gTUlTU19CTUEuZmlsKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLmZpbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMC4yNSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBpbmR2IiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IEZpcyB2cyBtaXNzaW5nIGRhdGEgcGVyIGluZHYgLS0tLQpwNSA8LSBnZ3Bsb3QoaW5kX3N0YXRzX2ZpbCwgYWVzKHggPSBGaXNfQk1BLmZpbCwgeSA9IE1JU1NfQk1BLmZpbCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKEZpc19CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwLjI1KSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIkZpcyBwZXIgaW5kdiIsIHkgPSAiJSBtaXNzaW5nIGRhdGEiKSArCiAgdGhlbWVfc3RhbmRhcmQKCiMgcGxvdCBGaXMgdnMgbWVhbiBkZXB0aCBwZXIgaW5kdiAtLS0tCnA2IDwtIGdncGxvdChpbmRfc3RhdHNfZmlsLCBhZXMoeCA9IEZpc19CTUEuZmlsLCB5ID0gTUVBTl9ERVBUSF9CTUEuZmlsKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oRmlzX0JNQS5maWwsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihNRUFOX0RFUFRIX0JNQS5maWwsIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDIwKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIkZpcyBwZXIgaW5kdiIsIHkgPSAibWVhbiBkZXB0aCBwZXIgaW5kdiIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IGRpc3RyaWJ1dGlvbiBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIC0tLS0KcDcgPC0gZ2dwbG90KGluZF9zdGF0c19maWwsIGFlcyh4ID0gTUlTU19CTUEuZmlsKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUlTU19CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwLjEpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAiJSBtaXNzaW5nIGRhdGEgcGVyIGxvY3VzIikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGlzdHJpYnV0aW9uIG1lYW4gcmVhZCBkZXB0aCAtLS0tCnA4IDwtIGdncGxvdChsb2Nfc3RhdHNfZmlsLCBhZXMoeCA9IE1FQU5fREVQVEhfQk1BLmZpbCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJkYXJrb3JhbmdlIikgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKE1FQU5fREVQVEhfQk1BLmZpbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHggPSAibWVhbiByZWFkIGRlcHRoIHBlciBsb2N1cyIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IHJlYWQgZGVwdGggdnMgbWlzc2luZyBkYXRhIC0tLS0KcDkgPC0gZ2dwbG90KGxvY19zdGF0c19maWwsIGFlcyh4ID0gTUVBTl9ERVBUSF9CTUEuZmlsLCB5ID0gTUlTU19CTUEuZmlsKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW4oTUVBTl9ERVBUSF9CTUEuZmlsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtZWFuKE1JU1NfQk1BLmZpbCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMC4xKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh4ID0gIm1lYW4gZGVwdGggcGVyIGxvY3VzIiwgeSA9ICIlIG1pc3NpbmcgZGF0YSIpICsKICB0aGVtZV9zdGFuZGFyZAoKIyBwbG90IG5vIG9mIFNOUHMgcGVyIGxvY3VzIC0tLS0KcDEwIDwtIGxvY19zdGF0c19maWwgJT4lCiAgY291bnQoQ0hSKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBuKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImRhcmtvcmFuZ2UiKSArIAogIGxhYnMoeCA9ICJudW1iZXIgb2YgU05QcyBwZXIgbG9jdXMiKSArCiAgdGhlbWVfc3RhbmRhcmQKCnRlbXAgPC0gbG9jX3N0YXRzX2ZpbCAlPiUKICBjb3VudChDSFIpCgojIHBsb3QgbnVtYmVyIG9mIFNOUHMgcGVyIGNvbnRpZyB2cy4gbWVhbiBkZXB0aCAtLS0tCnAxMSA8LSBsZWZ0X2pvaW4odGVtcCwgbG9jX3N0YXRzX2ZpbCkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoYWVzKHggPSBuLCB5ID0gTUVBTl9ERVBUSF9CTUEuZmlsKSkgKwogIGxhYnMoeCA9ICJudW1iZXIgb2YgU05QcyBwZXIgY29udGlnIiwgeSA9ICJtZWFuIGRlcHRoIikgKwogIHRoZW1lX3N0YW5kYXJkCgojIHBsb3QgZGVwdGggdnMgU05QIHF1YWxpdHkgLS0tLQpzaXRlX3F1YWwgPC0gcmVhZC50YWJsZSgiZGF0YS9WQ0YvQk1BLmZpbC5scXVhbCIsIAogICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JQogIG11dGF0ZShQUk9CID0gMTBeKC1RVUFMLzEwKSkKCnRlbXAgPC0gZGF0YS5mcmFtZShsb2Nfc3RhdHNfZmlsJE1FQU5fREVQVEhfQk1BLmZpbCwgc2l0ZV9xdWFsJFFVQUwpICU+JQogIHJlbmFtZShkZXB0aCA9IGxvY19zdGF0c19maWwuTUVBTl9ERVBUSF9CTUEuZmlsLCBxdWFsID0gc2l0ZV9xdWFsLlFVQUwpCgpwMTIgPC0gZ2dwbG90KHRlbXAsIGFlcyh4ID0gZGVwdGgsIHkgPSBxdWFsKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihkZXB0aCwgbmEucm0gPSBUUlVFKSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjApLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImRhcmtibHVlIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbihxdWFsLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAyMCksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiZGFya2JsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGxhYnMoeCA9ICJtZWFuIGRlcHRoIHBlciBsb2N1cyIsIHkgPSAiU05QIHF1YWxpdHkiKSArCiAgdGhlbWVfc3RhbmRhcmQKCm1maWwgPC0gbXVsdGlwbG90KHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgcDExLCBwMTIsIGNvbHM9MikKCmBgYAo=